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 #print (dir(objet_0))
205 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
207 nb_sub_results = objet_0.numberOfSubs()
210 print_tab(n_recur, "Examen de l'objet",objet_0.name())
211 texte = "Formé de {} sous-objets".format(nb_sub_results)
212 print_tab(n_recur, texte)
214 for n_sobj in range(nb_sub_results):
216 # 2.1. Exploration récursive de l'arborescence
218 couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b, verbose )
220 # 2.2. Cet objet n'a pas de sous-objets : on le colore
222 print_tab(n_recur, "Couleur affectée à l'objet ",objet_0.name())
223 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
225 #print ("sortie de {}".format(nom_fonction))
227 #========================= Fin de la fonction ===================================
229 #========================= Début de la fonction ==================================
231 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
232 """Imprime avec des tabulations
235 :nb_tab: nombre de tabulations à appliquer
236 :message: message principal
237 :argu: argument du format
238 :saut_av: saut de ligne avant le texte
239 :saut_ap: saut de ligne après le texte
247 for _ in range(nb_tab):
251 if ( argu is not None ):
252 texte += "{}".format(argu)
259 #========================= Fin de la fonction ===================================
261 #========================= Début de la fonction ==================================
263 def nommage (objet, nom, couleur=None):
264 """Nomme un objet et son résultat
267 :objet: objet à traiter
268 :nom: nom à attribuer
269 :couleur: éventuellement couleur
273 objet.result().setName(nom)
275 if ( couleur is not None ):
276 objet.result().setColor(couleur[0], couleur[1], couleur[2])
278 #========================= Fin de la fonction ===================================
280 #========================= Début de la fonction ==================================
282 def exec_nom (fonction, nom=None, couleur=None):
283 """Exécute la fonction puis éventuellement la nomme et nomme son résultat ; Couleur éventuelle
285 Attention : il faut commencer par exécuter la fonction sinon l enommage n'est pas cohérent en mode macro. Mystère...
288 :fonction: fonction à traiter
289 :nom: nom à attribuer éventuellement
290 :couleur: éventuellement couleur
293 fonction.execute(True)
295 if ( nom is not None ):
296 nommage (fonction, nom, couleur)
298 #========================= Fin de la fonction ===================================
301 #=================================== La classe ===================================
303 class SurfaceMediane (object):
305 """Calcul des surfaces médianes de solides minces
307 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
308 une structure qui est un solide ou un assemblage de solides (compound).
309 Pour réaliser l'opération, trois façons de faire :
311 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
313 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
314 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
316 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
317 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
320 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
321 de taille identique et supérieure aux tailles des autres faces du solide. \
322 Cela fonctionne pour des surfaces planes ou de forme canonique.
323 Il crée alors une surface au milieu de ces deux grandes faces. \
324 Cette face est coloriée en vert, le solide est en vert et transparent.
326 On sait traiter les faces :
333 Si la création n'a pas eu lieu, un message est émis et les solides sont mis en couleur :
334 . Rouge : le solide n'est pas assez mince.
335 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
336 . Orange : la forme de la face n'est pas reconnue.
344 . Exportation finale dans un fichier step. Par défaut, pas d'export.
345 -export_step/-no_export_step
348 surf_fic_cao --> import_cao
349 --> surf_objet_shaper (récursif) --> _nom_sous_objets
350 --> _surf_objet_shaper_0
351 --> surf_solide_shaper --> _isole_solide --> _isole_solide_a
353 --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
355 --> _cree_face_mediane
357 _cree_face_mediane --> _cree_face_mediane_plane
358 --> _cree_face_mediane_cylindre
359 --> _cree_face_mediane_sphere
360 --> _cree_face_mediane_tore
361 --> _cree_face_mediane_cone
362 --> _cree_face_mediane_0
371 affiche_aide_globale = 0
378 nom_solide_aux = None
384 objet_principal = None
385 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
387 # Statut de chaque sous-objet connu par son nom :
388 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
390 # Liste des faces médianes créées et des fonctions initiales
392 # La fonction initiale
398 #=========================== Début de la méthode =================================
400 def __init__ ( self, liste_option ):
402 """Le constructeur de la classe SurfaceMediane
404 Décodage des arguments
405 On cherche ici les arguments généraux : aide, verbeux
408 for option in liste_option :
411 if isinstance(option,str):
412 saux = option.upper()
414 if saux in ( "-H", "-HELP" ):
415 self.affiche_aide_globale = 1
418 elif saux == "-VMAX" :
420 self._verbose_max = 1
421 elif saux == "-EXPORT_STEP":
422 self._export_step = True
423 elif saux == "-NO_EXPORT_STEP":
424 self._export_step = False
426 #=========================== Fin de la méthode ==================================
428 #=========================== Début de la méthode =================================
431 """A la suppression de l'instance de classe"""
432 if self._verbose_max:
433 print ("Suppression de l'instance de la classe.")
435 #=========================== Fin de la méthode ==================================
437 #=========================== Début de la méthode =================================
439 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
440 """Gère les noms des sous_objets solides
443 :objet: objet à traiter
444 :lecture: vrai pour lire les noms, faux pour les attribuer
445 :n_recur: niveau de récursivité
446 :rang: rang du sous-objet
449 :rang: rang du sous-objet
452 nom_fonction = __name__ + "/_nom_sous_objets"
453 blabla = "Dans {} :\n".format(nom_fonction)
455 if self._verbose_max:
457 for _ in range(n_recur):
459 texte = "\n{}{}".format(prefixe,blabla)
460 texte += "{}n_recur = {}".format(prefixe,n_recur)
461 texte += "\n{}lecture = {}".format(prefixe,lecture)
464 # 1. Au premier passage, il faut garder la référence au résultat principal
467 objet_0 = objet.result()
468 if self._verbose_max:
469 print ("d_statut_so = {}".format(self.d_statut_so))
473 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
475 nb_sub_results = objet_0.numberOfSubs()
477 if self._verbose_max:
478 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
479 texte += "de type '{}'".format(objet_0.shapeType())
480 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
483 for n_sobj in range(nb_sub_results):
485 # 2.1. Exploration récursive de l'arborescence
487 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
489 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
491 if ( objet_0.shapeType() == "SOLID" ):
492 # A la lecture, on enregistre le nom
495 self.l_noms_so.append(nom)
496 self.d_statut_so[nom] = 0
497 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
499 nom = self.l_noms_so[rang]
501 etat = self.d_statut_so[nom]
502 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
504 objet_0.setTransparency (TRANSPARENCE)
509 #=========================== Fin de la méthode ==================================
511 #=========================== Début de la méthode =================================
513 def _isole_solide ( self, solide, n_recur ):
514 """Isole le solide de son arboresence
517 :solide: le solide à traiter
518 :n_recur: numéro de la récurrence
521 :objet: le solide isolé
522 :recover: la fonction de récupération
525 nom_fonction = __name__ + "/_isole_solide"
526 blabla = "Dans {} :".format(nom_fonction)
527 if self._verbose_max:
528 print_tab (n_recur, blabla)
529 texte = "Pour le solide '{}' ".format(solide.name())
530 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
531 print_tab (n_recur, texte)
533 if ( solide.name() != self.objet_principal.name() ):
534 objet, recover = self._isole_solide_a ( solide, n_recur )
537 objet, recover = self._isole_solide_b ( solide, n_recur )
539 if self._verbose_max:
540 print_tab (n_recur, "objet final : ", objet.name())
541 print_tab (n_recur, "fonction_0 : {}".format(self.fonction_0))
542 print_tab (n_recur, "recover : {}".format(recover))
544 return objet, recover
546 #=========================== Fin de la méthode ==================================
548 #=========================== Début de la méthode =================================
550 def _isole_solide_a ( self, solide, n_recur ):
551 """Isole le solide de son arboresence
554 :solide: le solide à traiter
555 :n_recur: numéro de la récurrence
558 :objet: le solide isolé
559 :recover: la fonction de récupération
562 nom_fonction = __name__ + "/_isole_solide_a"
563 blabla = "Dans {} :".format(nom_fonction)
564 if self._verbose_max:
565 print_tab (n_recur, blabla)
566 texte = "Pour le solide '{}' ".format(solide.name())
567 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
568 print_tab (n_recur, texte)
570 if self._verbose_max:
571 print_tab (n_recur, ". Extraction du solide '{}'".format(self.objet_principal.name()))
573 # 1. Extraction du solide
574 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
575 #exec_nom (remove_subshapes)
576 #print ('remove_subshapes = model.addRemoveSubShapes(part_doc, model.selection("COMPOUND", "{}"))'.format(self.objet_principal.name()))
577 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
578 #print ('remove_subshapes.setSubShapesToKeep([model.selection("SOLID", "{}")])'.format(solide.name()))
579 #exec_nom (remove_subshapes)
581 self.nom_solide_aux = "{}_S".format(solide.name())
582 if self._verbose_max:
583 print_tab (n_recur, "\tAttribution à remove_subshapes.result() du nom '{}'".format(self.nom_solide_aux))
584 exec_nom (remove_subshapes,self.nom_solide_aux)
586 self.fonction_0 = remove_subshapes
588 # 2. Récupération de l'objet principal
589 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
590 if self._verbose_max:
591 print_tab (n_recur, "\tAttribution à recover du nom '{}'".format(self.objet_principal.name()))
592 exec_nom (recover,self.objet_principal.name())
594 return remove_subshapes.result(), recover
596 #=========================== Fin de la méthode ==================================
598 #=========================== Début de la méthode =================================
600 def _isole_solide_b ( self, solide, n_recur ):
601 """Isole le solide de son arboresence
604 :solide: le solide à traiter
605 :n_recur: numéro de la récurrence
608 :objet: le solide isolé
609 :recover: la fonction de récupération
612 nom_fonction = __name__ + "/_isole_solide_b"
613 blabla = "Dans {} :".format(nom_fonction)
614 if self._verbose_max:
615 print_tab (n_recur, blabla)
616 texte = "Pour le solide '{}' ".format(solide.name())
617 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
618 print_tab (n_recur, texte)
620 if self._verbose_max:
621 print_tab (n_recur, ". Mise en place du solide")
623 self.nom_solide_aux = self.objet_principal.name()
624 self.fonction_0 = None
628 #=========================== Fin de la méthode ==================================
630 #=========================== Début de la méthode =================================
632 def _faces_du_solide ( self, solide, n_recur=0 ):
633 """Détermine les faces d'un solide
636 :solide: solide SHAPER à traiter
637 :n_recur: niveau de récursivité
640 :l_faces_car: pour chaque face du solide (surface,caractéristiques)
643 nom_fonction = __name__ + "/_faces_du_solide"
644 blabla = "Dans {} :".format(nom_fonction)
645 if self._verbose_max:
646 print_tab (n_recur, blabla, saut_av=True)
650 if self._verbose_max:
651 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
652 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
655 #print_tab (n_recur, "volume = ", GeomAlgoAPI_ShapeTools.volume(solide.shape()))
656 # 1. Repérage des faces
657 objResult = solide.resultSubShapePair()[0]
659 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
661 l_faces.append(exp.current().face())
666 for iface, face in enumerate(l_faces):
667 surf = GeomAlgoAPI_ShapeTools.area(face)
668 caract = geom.shapeInfo(face)
669 if self._verbose_max:
670 print_tab (n_recur, "\tFace n°{} ; ".format(iface), "surface = {}, caractéristiques = {}".format(surf,caract))
671 l_faces_car.append((surf,caract))
675 #=========================== Fin de la méthode ==================================
677 #=========================== Début de la méthode =================================
679 def _calcul_caract_faces ( self, solide, n_recur ):
680 """Calcule les caractéristiques géométriques des faces du solide
683 :solide: solide SHAPER à traiter
684 :n_recur: niveau de récursivité
687 :tb_caract: tableau des caractéristiques géométriques des faces
690 nom_fonction = __name__ + "/_calcul_caract_faces"
691 blabla = "Dans {} :".format(nom_fonction)
692 if self._verbose_max:
693 print_tab (n_recur, blabla, saut_av=True)
694 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
695 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
697 # 1. Repérage des faces
698 objResult = solide.resultSubShapePair()[0]
700 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
702 l_faces.append(exp.current().face())
705 # 2. Caractéristiques
706 nb_faces = len(l_faces)
707 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
708 for iaux, face in enumerate(l_faces):
709 surf = GeomAlgoAPI_ShapeTools.area(face)
710 caract = geom.shapeInfo(face)
711 if self._verbose_max:
712 print_tab (n_recur, "\tFace n°{} ; ".format(iaux), "surface = {}, caractéristiques = {}".format(surf,caract))
714 tb_caract [iaux][0] = face
715 tb_caract [iaux][1] = surf
716 tb_caract [iaux][2] = caract
718 #if self._verbose_max:
719 #for iaux in range(nb_faces):
720 #print ("\t. tb_caract : {} {}".format(surf,tb_caract[iaux][2]))
724 #=========================== Fin de la méthode ==================================
726 #=========================== Début de la méthode =================================
728 def _tri_faces ( self, tb_caract, n_recur ):
729 """Trie les faces en fonction de leurs surfaces
732 :tb_caract: tableau des caractéristiques géométriques des faces
733 :n_recur: niveau de récursivité
736 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
742 nom_fonction = __name__ + "/_tri_faces"
743 blabla = "Dans {} :".format(nom_fonction)
745 # 1. Tri du tableau en fonction des surfaces
746 if self._verbose_max:
747 print_tab (n_recur, blabla)
748 print_tab (n_recur, "tb_caract brut : ", tb_caract)
749 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
750 if self._verbose_max:
751 print_tab (n_recur, "tb_caract trié :", tb_caract_1)
753 if self._verbose_max:
754 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
755 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
758 # 2. La surface suivante doit être différente, sinon ce n'est pas un solide mince
759 if ( len(tb_caract) > 2 ):
761 if self._verbose_max:
762 texte += "\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
764 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
765 if ( ecart < self._epsilon ):
766 message = "\nSolide '{}'\n".format(self.nom_solide)
767 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
768 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
769 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
770 if self._verbose_max:
771 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
772 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
773 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
775 self.d_statut_so[self.nom_solide] = -1
776 self.faces_pb_nb += 1
777 self.faces_pb_msg += message
779 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
781 #=========================== Fin de la méthode ==================================
783 #=========================== Début de la méthode =================================
785 def _verif_epaisseur ( self, epaisseur ):
786 """Contrôle de la validité de l'épaisseur
789 :epaisseur: épaisseur du solide
792 nom_fonction = __name__ + "/_verif_epaisseur"
793 blabla = "Dans {} :\n".format(nom_fonction)
795 if self._verbose_max:
797 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
798 texte += ". EP_MIN : {}".format(EP_MIN)
801 if ( epaisseur <= EP_MIN ):
802 message = "\nSolide '{}'\n".format(self.nom_solide)
803 message += ". Epaisseur : {}\n".format(epaisseur)
804 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
805 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
807 self.d_statut_so[self.nom_solide] = 2
808 self.faces_pb_nb += 1
809 self.faces_pb_msg += message
813 #print ("erreur = {}".format(erreur))
817 #=========================== Fin de la méthode ==================================
819 #=========================== Début de la méthode =================================
821 def _cree_face_mediane ( self, solide, caract_face_1, caract_face_2, n_recur ):
822 """Crée la face médiane entre deux autres
825 :solide: solide SHAPER à traiter
826 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
827 :n_recur: niveau de récursivité
830 :face: la face médiane créée
833 nom_fonction = __name__ + "/_cree_face_mediane"
834 blabla = "Dans {} :".format(nom_fonction)
836 if self._verbose_max:
837 print_tab (n_recur, blabla)
838 print_tab (n_recur, "face_1 : " ,caract_face_1)
839 print_tab (n_recur, "face_2 : " ,caract_face_2)
844 # 1. Forme de la face
845 forme = caract_face_1[2][0]
847 # 2. Traitement selon la forme de la face
849 if forme in ( "Disk" , "Plane", "Rectangle"):
850 erreur, face = self._cree_face_mediane_plane ( solide, caract_face_1, caract_face_2, n_recur )
852 # 2.2. Face cylindrique
853 elif ( forme == "Cylinder" ):
854 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
856 # 2.3. Face sphérique
857 elif ( forme == "Sphere" ):
858 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
861 elif ( forme == "Torus" ):
862 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
865 elif ( forme == "Cone" ):
866 erreur, face = self._cree_face_mediane_cone ( caract_face_1, caract_face_2, n_recur )
868 # 2.N. Face de forme inconnue
870 message = "\nSolide '{}'\n".format(self.nom_solide)
871 message += "sa face la plus grande est de forme : {}\n".format(forme)
872 message += "==> Impossible de créer la face médiane.\n"
874 self.d_statut_so[self.nom_solide] = -2
875 self.faces_pb_nb += 1
876 self.faces_pb_msg += message
878 # 3. Gestion de la face produite
881 self._cree_face_mediane_0 ( face, n_recur )
883 if self._verbose_max:
884 print_tab (n_recur, "Sortie de "+blabla)
888 #=========================== Fin de la méthode ==================================
890 #=========================== Début de la méthode =================================
892 def _cree_face_mediane_0 ( self, face, n_recur ):
893 """Gestion de la face médiane créée entre deux autres
896 :face: la face médiane créée
897 :n_recur: niveau de récursivité
900 nom_fonction = __name__ + "/_cree_face_mediane_0"
901 blabla = "Dans {} :".format(nom_fonction)
903 if self._verbose_max:
904 print_tab (n_recur, blabla)
907 nom_face = self.nom_solide+"_M"
908 if self._verbose_max:
909 print_tab (n_recur,"Nom de la face créée : ", nom_face)
910 #if ( self.nom_solide_aux != self.objet_principal.name() ):
912 nommage (face, nom_face)
914 # 2. Mémorisation de la face et de la fonction initiale
915 self.l_faces_m.append((face, self.fonction_0))
917 # 3. Couleur verte pour la face
918 couleur_objet (face, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
920 # 4. Changement de statut pour le solide
921 self.d_statut_so[self.nom_solide] = 1
923 if self._verbose_max:
924 print_tab (n_recur, "Sortie de _cree_face_mediane_0")
926 #=========================== Fin de la méthode ==================================
928 #=========================== Début de la méthode =================================
930 def _cree_face_mediane_plane ( self, solide, caract_face_1, caract_face_2, n_recur ):
931 """Crée la face médiane entre deux autres - cas des surfaces planes
934 :solide: l'objet solide à traiter
935 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
936 :n_recur: niveau de récursivité
939 :face: la face médiane
942 nom_fonction = __name__ + "/_cree_face_mediane_plane"
943 blabla = "Dans {} :".format(nom_fonction)
944 if self._verbose_max:
945 print_tab (n_recur, blabla)
947 # Caractéristiques des surfaces
948 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 )
950 # Contrôle de la validité de l'épaisseur
951 erreur = self._verif_epaisseur ( d_face_1_2 )
953 # Création de la face
955 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 )
961 #=========================== Fin de la méthode ==================================
963 #=========================== Début de la méthode =================================
965 def _cree_face_mediane_plane_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
966 """Crée la face médiane entre deux autres - cas des surfaces planes
968 Décodage des caractéristiques
971 :solide: l'objet solide à traiter
972 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
973 :n_recur: niveau de récursivité
976 :coo_x, coo_y, coo_z: coordonnées du centre de la base
977 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
978 :taille: estimation de la taille de la future face
979 :d_face_1_2: la distance entre les deux faces
982 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
983 blabla = "Dans {} :".format(nom_fonction)
985 if self._verbose_max:
986 print_tab (n_recur, blabla)
987 print_tab (n_recur, "caract_face_1 : ", caract_face_1)
988 print_tab (n_recur, "caract_face_2 : ", caract_face_2)
990 # 1. Caractéristiques de la base
991 # Coordonnées du centre de la base
992 coo_x = caract_face_1[2][1]
993 coo_y = caract_face_1[2][2]
994 coo_z = caract_face_1[2][3]
995 # Coordonnées du vecteur normal
996 vnor_x = caract_face_1[2][4]
997 vnor_y = caract_face_1[2][5]
998 vnor_z = caract_face_1[2][6]
999 # taille : une longueur caractéristique pour être certain de tout prendre
1000 l_diag = self._calcul_lg_caract ( solide, n_recur )
1002 if self._verbose_max:
1003 print_tab (n_recur, "Taille englobante : ",taille)
1005 # 2. Distance entre les deux faces
1006 face_1 = caract_face_1[0]
1007 face_2 = caract_face_2[0]
1008 d_face_1_2 = GeomAlgoAPI_ShapeTools.minimalDistance(face_1, face_2)
1009 if self._verbose_max:
1010 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
1012 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
1014 #=========================== Fin de la méthode ==================================
1016 #=========================== Début de la méthode =================================
1018 def _cree_face_mediane_plane_1 ( self, solide, coo_c, vnor, taille, d_face_1_2, n_recur ):
1019 """Crée la face médiane entre deux autres - cas des surfaces planes
1021 Création des objets de construction et de la face médiane
1024 :solide: l'objet solide à traiter
1025 :coo_c: coordonnées du centre de la base
1026 :vnor: coordonnées du vecteur normal
1027 :taille: estimation de la taille de la future face
1028 :d_face_1_2: la distance entre les deux faces
1029 :n_recur: niveau de récursivité
1032 :face: la face médiane
1035 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
1036 blabla = "Dans {} :".format(nom_fonction)
1037 if self._verbose_max:
1038 print_tab (n_recur, blabla)
1039 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1040 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
1041 print_tab (n_recur, "Taille : ", taille)
1042 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1045 _, v_norm, plan = self._cree_centre_axe_plan ( coo_c, vnor, self.nom_solide, n_recur )
1047 # 2. Création de l'esquisse
1048 sketch = self._cree_face_mediane_plane_1_a ( plan, taille, n_recur )
1051 face = self._cree_face_mediane_plane_1_b ( solide, sketch, v_norm, d_face_1_2, n_recur )
1053 #print ("fin de {}".format(nom_fonction))
1057 #=========================== Fin de la méthode ==================================
1059 #=========================== Début de la méthode =================================
1061 def _cree_face_mediane_plane_1_a ( self, plan, taille, n_recur ):
1062 """Crée la face médiane entre deux autres - cas des surfaces planes - l'esquisse
1066 :taille: estimation de la taille de la future face
1067 :n_recur: niveau de récursivité
1073 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_a"
1074 blabla = "Dans {} :".format(nom_fonction)
1075 if self._verbose_max:
1076 print_tab (n_recur, blabla)
1077 print_tab (n_recur, "Plan : {}".format(plan.name()))
1078 print_tab (n_recur, "taille : {}".format(taille))
1080 sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1081 sketch.execute(True)
1083 ### Create SketchLine
1084 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1085 SketchLine_1.execute(True)
1087 ### Create SketchLine
1088 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1089 SketchLine_2.execute(True)
1091 ### Create SketchLine
1092 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1093 SketchLine_3.execute(True)
1095 ### Create SketchLine
1096 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1097 SketchLine_4.execute(True)
1101 nom_sketch = "{}_esquisse".format(self.nom_solide)
1102 exec_nom (sketch,nom_sketch)
1104 #print ("fin de {}".format(nom_fonction))
1108 #=========================== Fin de la méthode ==================================
1110 #=========================== Début de la méthode =================================
1112 def _cree_face_mediane_plane_1_b ( self, solide, sketch, v_norm, d_face_1_2, n_recur ):
1113 """Crée la face médiane entre deux autres - cas des surfaces planes
1115 Création de la face médiane
1118 :solide: l'objet solide à traiter
1120 :v_norm: vecteur normal
1121 :d_face_1_2: la distance entre les deux faces
1122 :n_recur: niveau de récursivité
1125 :face: la face médiane
1128 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_b"
1129 blabla = "Dans {} :".format(nom_fonction)
1130 if self._verbose_max:
1131 print_tab (n_recur, blabla)
1132 print_tab (n_recur, "Esquisse : ", sketch.name())
1133 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1135 # 1. Copie du solide pour gérer les intersections
1136 #Copy_1 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1137 Copy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1138 nom = "{}_Copy_1".format(self.nom_solide_aux)
1139 exec_nom (Copy_1,nom)
1140 if self._verbose_max:
1141 print_tab (n_recur, "Après addMultiTranslation Copy_1 de nom ", nom)
1142 nom_solide = Copy_1.result().name()
1145 Recover_1 = model.addRecover(self.part_doc, Copy_1, [solide])
1146 nom = "{}_Recover_1".format(self.nom_solide_aux)
1147 exec_nom (Recover_1,nom)
1148 if self._verbose_max:
1149 print_tab (n_recur, "Après addRecover Recover_1 de nom ", nom)
1151 # 2. Création d'une face ; on la translate d'une demi-épaisseur.
1152 for iaux in range(2):
1154 # 2.1. Création d'une face à partir du sketch et translation perpendiculaire au plan de la face
1155 # On essaie les 2 côtés alternativement car on ne sait pas lequel sera le bon
1157 d_trans = -0.5*d_face_1_2*float(2*iaux-1)
1159 face = self._cree_face_mediane_plane_2 ( sketch.name(), v_norm.name(), nom_solide, d_trans, iaux, n_recur )
1161 # 2.2. Si on est du bon côté, alors on intersecte la face avec le solide et c'est bon
1163 face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1166 # 2.3. Si l'intersection est vide, on crée une nouvelle copie du solide avant de tester l'autre côté
1168 if self._verbose_max:
1169 print_tab (n_recur, "L'intersection est vide. On essaie l'autre côté")
1171 ### Create LinearCopy
1172 #Copy_2 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1173 Copy_2 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", Recover_1.result().name())], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1174 nom = "{}_Copy_2".format(self.nom_solide_aux)
1175 exec_nom (Copy_2,nom)
1176 if self._verbose_max:
1177 print_tab (n_recur, "Après addMultiTranslation Copy_2 de nom ", nom)
1178 nom_solide = Copy_2.result().name()
1180 #print ("fin de {}".format(nom_fonction))
1184 #=========================== Fin de la méthode ==================================
1186 #=========================== Début de la méthode =================================
1188 def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1189 """Crée la face médiane entre deux autres - cas des surfaces planes
1191 Création des objets de construction et de la face médiane
1194 :face: la face médiane
1195 :Recover_1: la récupératiuon du solide
1196 :n_recur: niveau de récursivité
1199 :face: la face médiane
1202 nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1203 blabla = "Dans {} :".format(nom_fonction)
1204 if self._verbose_max:
1205 print_tab (n_recur, blabla)
1206 print_tab (n_recur, "face : ", face.name())
1208 # Si on traite un objet solide unique, on le récupère
1209 if ( self.nom_solide_aux == self.objet_principal.name() ):
1210 if self._verbose_max:
1211 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1212 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1213 nom = "{}_Recover_2".format(self.nom_solide_aux)
1214 exec_nom (Recover_2,nom)
1216 nb_inter = face.result().numberOfSubs()
1217 if self._verbose_max:
1218 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1221 face = self._cree_face_mediane_plane_3 ( face )
1225 #=========================== Fin de la méthode ==================================
1227 #=========================== Début de la méthode =================================
1229 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, d_trans, icpt, n_recur ):
1230 """Crée la face médiane entre deux autres - cas des surfaces planes
1232 Intersection de la face avec le solide
1235 :nom_sketch: nom de l'esquisse
1236 :nom_normal: nom du vecteur normal
1237 :nom_solide: nom du solide à intersecter
1238 :d_trans: la distance de translation
1239 :icpt: numéro de la tentative
1242 :face: la face médiane
1245 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1246 blabla = "Dans {} :".format(nom_fonction)
1247 if self._verbose_max:
1248 print_tab (n_recur, blabla)
1249 print_tab (n_recur, "nom_sketch : ", nom_sketch)
1250 print_tab (n_recur, "nom_normal : ", nom_normal)
1251 print_tab (n_recur, "nom_solide : ", nom_solide)
1252 print_tab (n_recur, "d_trans : ", d_trans)
1254 # Création d'une face
1255 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1256 nom = "{}_Face_1_{}".format(self.nom_solide_aux,icpt)
1257 exec_nom (Face_1,nom)
1258 if self._verbose_max:
1259 print_tab (n_recur, "Après addFace pour Face_1 de nom ", nom)
1262 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)
1263 nom = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1264 exec_nom (Translation_1,nom)
1265 if self._verbose_max:
1266 print_tab (n_recur, "Après addTranslation pour Translation_1 de nom ", nom)
1267 Translation_1.result().setColor(85, 0, 255)
1269 # Intersection de cette face avec le solide initial
1270 face = self._creation_face_inter ( Translation_1.result().name(), nom_solide )
1274 #=========================== Fin de la méthode ==================================
1276 #=========================== Début de la méthode =================================
1278 def _cree_face_mediane_plane_3 ( self, face ):
1279 """Crée la face médiane entre deux autres - cas des surfaces planes
1281 Fusion des 2 intersections
1284 :face: la face médiane composée de plusieurs intersections
1287 :face_m: la face médiane
1290 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1291 blabla = "Dans {} :\n".format(nom_fonction)
1292 if self._verbose_max:
1296 # Nommage des sous-objets
1298 for iaux in range(face.result().numberOfSubs()):
1299 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1300 face.result().subResult(iaux).setName(nom)
1301 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1304 if self._verbose_max:
1305 print ("Fusion de {} faces.".format(len(l_fuse)))
1306 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1307 face_m.execute(True)
1311 #=========================== Fin de la méthode ==================================
1313 #=========================== Début de la méthode =================================
1315 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1316 """Crée la face médiane entre deux autres - cas des cylindres
1319 :solide: solide SHAPER à traiter
1320 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1321 :n_recur: niveau de récursivité
1324 :face: la face médiane
1327 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1328 blabla = "Dans {} :".format(nom_fonction)
1331 if self._verbose_max:
1332 print_tab (n_recur, blabla)
1333 print_tab (n_recur, "face_1 : ", caract_face_1)
1334 print_tab (n_recur, "face_2 : ", caract_face_2)
1336 # Caractéristiques des cylindres
1337 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 )
1339 # Contrôle de la validité de l'épaisseur
1340 erreur = self._verif_epaisseur ( epaisseur )
1342 # Création de la face, de couleur bleue si problème
1344 face = self._cree_face_mediane_cylindre_1 ( (coo_x, coo_y, coo_z), (axe_x, axe_y, axe_z), rayon, hauteur, n_recur )
1346 couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255, verbose=self._verbose_max)
1351 #=========================== Fin de la méthode ==================================
1353 #=========================== Début de la méthode =================================
1355 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1356 """Crée la face médiane entre deux autres - cas des cylindres
1358 Décodage des caractéristiques
1361 :solide: l'objet solide à traiter
1362 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1363 :n_recur: niveau de récursivité
1366 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1367 :axe_x, axe_y, axe_z: coordonnées de l'axe
1368 :rayon: rayon moyen entre les deux faces
1369 :hauteur: hauteur du cylindre
1370 :epaisseur: épaisseur de l'interface entre les deux faces
1373 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1374 blabla = "Dans {} :".format(nom_fonction)
1376 if self._verbose_max:
1377 print_tab (n_recur, blabla)
1378 print_tab (n_recur, "face_1 : ", caract_face_1)
1379 print_tab (n_recur, "face_2 : ", caract_face_2)
1381 # Coordonnées du centre de la base
1382 coo_x = caract_face_1[2][1]
1383 coo_y = caract_face_1[2][2]
1384 coo_z = caract_face_1[2][3]
1385 # Coordonnées de l'axe
1386 axe_x = caract_face_1[2][4]
1387 axe_y = caract_face_1[2][5]
1388 axe_z = caract_face_1[2][6]
1390 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1391 # Hauteur : une longueur caractéristique pour être certain de tout prendre
1392 l_diag = self._calcul_lg_caract ( solide, n_recur )
1393 hauteur = 10.*l_diag
1394 if self._verbose_max:
1395 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1397 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1399 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1401 #=========================== Fin de la méthode ==================================
1403 #=========================== Début de la méthode =================================
1405 def _cree_face_mediane_cylindre_1 ( self, coo_c, v_axe, rayon, hauteur, n_recur ):
1406 """Crée la face médiane entre deux autres - cas des cylindres
1408 Création des objets temporaires et de la face externe du cylindre support
1411 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1412 :axe_x, axe_y, axe_z: coordonnées de l'axe
1413 :rayon: rayon moyen entre les deux faces
1414 :hauteur: hauteur du cylindre
1415 :n_recur: niveau de récursivité
1418 :face: la face médiane
1420 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1421 blabla = "Dans {} :\n".format(nom_fonction)
1423 # Les caractéristiques du cylindre à créer
1424 if self._verbose_max:
1425 print_tab (n_recur, blabla)
1426 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1427 print_tab (n_recur, "Axe : ({}, {}, {})".format(v_axe[0], v_axe[1], v_axe[2]))
1428 print_tab (n_recur, "Rayon : ", rayon)
1429 print_tab (n_recur, "Hauteur : ", hauteur)
1431 # 1. Création du point central
1432 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1433 nom_centre = "{}_centre".format(self.nom_solide)
1434 exec_nom (centre,nom_centre)
1435 if self.fonction_0 is None:
1436 self.fonction_0 = centre
1438 # 2. Création du vecteur axial
1439 axe = model.addAxis(self.part_doc, v_axe[0], v_axe[1], v_axe[2])
1440 nom_axe = "{}_vecteur".format(self.nom_solide)
1441 exec_nom (axe,nom_axe)
1443 # 3. Création du cylindre en volume, de rayon médian
1444 Cylinder_1 = model.addCylinder(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon, hauteur)
1445 nom = "{}_Cylinder_1".format(self.nom_solide)
1446 exec_nom (Cylinder_1,nom)
1448 # 4. Création du cylindre en surface
1449 cylindre = self._creation_face_surface ( nom, "cylindre" )
1452 Translation_1 = model.addTranslation(self.part_doc, [model.selection("COMPOUND", cylindre.name())], axis = model.selection("EDGE", nom_axe), distance = -0.5*hauteur, keepSubResults = True)
1453 nom = "{}_Translation_1".format(self.nom_solide)
1454 exec_nom (Translation_1,nom)
1456 # 6. Intersection de la face cylindrique avec le solide initial
1457 face = self._creation_face_inter ( nom )
1461 #=========================== Fin de la méthode ==================================
1463 #=========================== Début de la méthode =================================
1465 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1466 """Crée la face médiane entre deux autres - cas des sphères
1469 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1470 :n_recur: niveau de récursivité
1473 :face: la face médiane
1476 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1477 blabla = "Dans {} :".format(nom_fonction)
1480 if self._verbose_max:
1481 print_tab (n_recur, blabla)
1482 print_tab (n_recur, "face_1 : ", caract_face_1)
1483 print_tab (n_recur, "face_2 : ", caract_face_2)
1485 # Caractéristiques des sphères
1486 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1488 # Contrôle de la validité de l'épaisseur
1489 erreur = self._verif_epaisseur ( epaisseur )
1491 # Création de la face
1493 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1499 #=========================== Fin de la méthode ==================================
1501 #=========================== Début de la méthode =================================
1503 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1504 """Crée la face médiane entre deux autres - cas des sphères
1506 Décodage des caractéristiques
1509 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1510 :n_recur: niveau de récursivité
1513 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1514 :rayon: rayon moyen entre les deux faces
1515 :epaisseur: épaisseur de l'interface entre les deux faces
1518 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1519 blabla = "Dans {} :".format(nom_fonction)
1522 if self._verbose_max:
1523 print_tab (n_recur, blabla)
1524 print_tab (n_recur, "face_1 : ", caract_face_1)
1525 print_tab (n_recur, "face_2 : ", caract_face_2)
1527 # Coordonnées du centre de la sphère
1528 coo_x = caract_face_1[2][1]
1529 coo_y = caract_face_1[2][2]
1530 coo_z = caract_face_1[2][3]
1532 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1534 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1536 return coo_x, coo_y, coo_z, rayon, epaisseur
1538 #=========================== Fin de la méthode ==================================
1540 #=========================== Début de la méthode =================================
1542 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1543 """Crée la face médiane entre deux autres - cas des sphères
1545 Création des objets de construction et de la face externe de la sphère support
1548 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1549 :rayon: rayon moyen entre les deux faces
1552 :face: la face externe de la sphère support
1555 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1556 blabla = "Dans {} :\n".format(nom_fonction)
1558 # Les caractéristiques de la sphère à créer
1559 if self._verbose_max:
1561 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1562 texte += "Rayon : {}".format(rayon)
1565 # 1. Création du point central
1566 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1567 nom_centre = "{}_centre".format(self.nom_solide)
1568 exec_nom (centre,nom_centre)
1569 if self.fonction_0 is None:
1570 self.fonction_0 = centre
1572 # 2. Création de la sphère en volume, de rayon médian
1573 Sphere_1 = model.addSphere(self.part_doc, model.selection("VERTEX", nom_centre), rayon)
1574 nom = "{}_Sphere_1".format(self.nom_solide)
1575 exec_nom (Sphere_1,nom)
1577 # 3. Création de la sphère en surface
1578 sphere = self._creation_face_surface ( nom, "sphere" )
1580 # 4. Intersection de la face sphérique avec le solide initial
1581 face = self._creation_face_inter ( sphere.name() )
1585 #=========================== Fin de la méthode ==================================
1587 #=========================== Début de la méthode =================================
1589 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1590 """Crée la face médiane entre deux autres - cas des tores
1593 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1594 :n_recur: niveau de récursivité
1597 :face: la face médiane
1600 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1601 blabla = "Dans {} :".format(nom_fonction)
1604 if self._verbose_max:
1605 print_tab (n_recur, blabla)
1606 print_tab (n_recur, "face_1 : ", caract_face_1)
1607 print_tab (n_recur, "face_2 : ", caract_face_2)
1609 # Caractéristiques des tores
1610 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 )
1612 # Contrôle de la validité de l'épaisseur (bidon)
1613 erreur = self._verif_epaisseur ( EP_MIN*10. )
1615 # Création de la face
1617 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1623 #=========================== Fin de la méthode ==================================
1625 #=========================== Début de la méthode =================================
1627 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1628 """Crée la face médiane entre deux autres - cas des tores
1630 Décodage des caractéristiques
1633 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1634 :n_recur: niveau de récursivité
1637 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1638 :axe_x, axe_y, axe_z: coordonnées de l'axe
1639 :rayon_1 : rayon principal
1640 :rayon_2 : rayon secondaire
1643 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1644 blabla = "Dans {} :".format(nom_fonction)
1647 if self._verbose_max:
1648 print_tab (n_recur, blabla)
1649 print_tab (n_recur, "face_1 : ", caract_face_1)
1650 print_tab (n_recur, "face_2 : ", caract_face_2)
1652 # Coordonnées du centre du tore
1653 coo_x = caract_face_1[2][1]
1654 coo_y = caract_face_1[2][2]
1655 coo_z = caract_face_1[2][3]
1656 # Coordonnées de l'axe
1657 axe_x = caract_face_1[2][4]
1658 axe_y = caract_face_1[2][5]
1659 axe_z = caract_face_1[2][6]
1661 rayon_1 = caract_face_2[2][7]
1662 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1664 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1666 #=========================== Fin de la méthode ==================================
1668 #=========================== Début de la méthode =================================
1670 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1671 """Crée la face médiane entre deux autres - cas des tores
1673 Création des objets de construction et de la face externe du tore support
1676 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1677 :axe_x, axe_y, axe_z: coordonnées de l'axe
1678 :rayon_1 : rayon principal
1679 :rayon_2 : rayon secondaire
1682 :face: la face externe du tore support
1685 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1686 blabla = "Dans {} :\n".format(nom_fonction)
1689 if self._verbose_max:
1691 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1692 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1693 texte += "Rayon principal : {}\n".format(rayon_1)
1694 texte += "Rayon secondaire : {}".format(rayon_2)
1697 # 1. Création du point central
1698 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1699 nom_centre = "{}_centre".format(self.nom_solide)
1700 exec_nom (centre,nom_centre)
1702 # 2. Création de l'axe
1703 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1704 nom_axe = "{}_axe".format(self.nom_solide)
1705 exec_nom (axe,nom_axe)
1707 # 3. Création du tore en volume, de rayon médian
1708 Tore_1 = model.addTorus(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon_1, rayon_2)
1709 nom = "{}_Tore_1".format(self.nom_solide)
1710 exec_nom (Tore_1,nom)
1712 # 4. Création du tore en surface
1713 tore = self._creation_face_surface ( nom, "tore" )
1715 # 5. Intersection de la face torique avec le solide initial
1716 face = self._creation_face_inter ( tore.name() )
1720 #=========================== Fin de la méthode ==================================
1722 #=========================== Début de la méthode =================================
1724 def _cree_face_mediane_cone ( self, caract_face_1, caract_face_2, n_recur ):
1725 """Crée la face médiane entre deux autres - cas des cones
1728 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1729 :n_recur: niveau de récursivité
1732 :face: la face médiane
1735 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1736 blabla = "Dans {} :".format(nom_fonction)
1739 if self._verbose_max:
1740 print_tab (n_recur, blabla)
1741 print_tab (n_recur, "face_1 : ", caract_face_1)
1742 print_tab (n_recur, "face_2 : ", caract_face_2)
1744 # Caractéristiques des cones
1745 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 )
1747 # Contrôle de la validité de l'épaisseur (bidon)
1748 erreur = self._verif_epaisseur ( EP_MIN*10. )
1750 # Création de la face
1752 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1758 #=========================== Fin de la méthode ==================================
1760 #=========================== Début de la méthode =================================
1762 def _cree_face_mediane_cone_0 ( self, caract_face_1, caract_face_2, n_recur ):
1763 """Crée la face médiane entre deux autres - cas des cones
1765 Décodage des caractéristiques
1768 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1769 :n_recur: niveau de récursivité
1772 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1773 :axe_x, axe_y, axe_z: coordonnées de l'axe
1774 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1775 :hauteur: hauteur du cone
1778 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1779 blabla = "Dans {} :".format(nom_fonction)
1782 if self._verbose_max:
1783 print_tab (n_recur, blabla)
1784 print_tab (n_recur, "face_1 : ", caract_face_1)
1785 print_tab (n_recur, "face_2 : ", caract_face_2)
1787 # Coordonnées du centre de la base
1788 coo_x = caract_face_1[2][1]
1789 coo_y = caract_face_1[2][2]
1790 coo_z = caract_face_1[2][3]
1791 # Coordonnées de l'axe
1792 axe_x = caract_face_1[2][4]
1793 axe_y = caract_face_1[2][5]
1794 axe_z = caract_face_1[2][6]
1796 rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1797 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1799 hauteur = caract_face_1[2][9]
1802 if self._verbose_max:
1803 print_tab (n_recur, "coo_x : ", coo_x)
1804 print_tab (n_recur, "coo_y : ", coo_y)
1805 print_tab (n_recur, "coo_z : ", coo_z)
1806 print_tab (n_recur, "axe_x : ", axe_x)
1807 print_tab (n_recur, "axe_y : ", axe_y)
1808 print_tab (n_recur, "axe_z : ", axe_z)
1809 print_tab (n_recur, "rayon_1 : ", rayon_1)
1810 print_tab (n_recur, "rayon_2 : ", rayon_2)
1811 print_tab (n_recur, "hauteur : ", hauteur)
1813 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1815 #=========================== Fin de la méthode ==================================
1817 #=========================== Début de la méthode =================================
1819 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1820 """Crée la face médiane entre deux autres - cas des cones
1822 Création des objets de construction et de la face externe du cone support
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 :face: la face externe du cone support
1833 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1834 blabla = "Dans {} :\n".format(nom_fonction)
1837 if self._verbose_max:
1839 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1840 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1841 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1842 texte += "Hauteur : {}".format(hauteur)
1845 # 1. Création du point central de la base, côté rayon_1
1846 centre_1 = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1847 nom_centre_1 = "{}_centre_1".format(self.nom_solide)
1848 exec_nom (centre_1,nom_centre_1)
1850 # 2. Création du point central, du côté de rayon_2
1851 centre_2 = model.addPoint(self.part_doc, coo_x+hauteur*axe_x, coo_y+hauteur*axe_y, coo_z+hauteur*axe_z)
1852 nom_centre_2 = "{}_centre_2".format(self.nom_solide)
1853 exec_nom (centre_2,nom_centre_2)
1855 # 3. Création de l'axe
1856 axe = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("VERTEX", nom_centre_2))
1857 nom_axe = "{}_axe".format(self.nom_solide)
1858 exec_nom (axe,nom_axe)
1860 # 4. Création d'un plan passant par le centre de la base et l'axe
1861 # 4.1. Création d'un vecteur perpendiculaire à l'axe
1863 if ( (abs(axe_x)+abs(axe_y)) < self._epsilon ):
1864 v_perp = model.addAxis(self.part_doc, coeff, 0., 0.)
1866 v_perp = model.addAxis(self.part_doc, -coeff*axe_y, coeff*axe_x, 0.)
1867 nom_v_perp = "{}_v_perp".format(self.nom_solide)
1868 exec_nom (v_perp,nom_v_perp)
1869 # 4.2. Création du plan
1870 plan = model.addPlane(self.part_doc, model.selection("EDGE",nom_v_perp), model.selection("VERTEX", nom_centre_1), True)
1871 nom_plan = "{}_plan".format(self.nom_solide)
1872 exec_nom (plan,nom_plan)
1875 nom_par_1 = "{}_R_1".format(self.nom_solide)
1876 param = model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1878 nom_par_2 = "{}_R_2".format(self.nom_solide)
1879 param = model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1881 nom_par_3 = "{}_H".format(self.nom_solide)
1882 param = model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
1885 # 6. Création de l'esquisse
1887 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1888 sketch.execute(True)
1890 # 6.1. Projection des centres et de l'axe
1891 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre_1), False)
1892 SketchProjection_1.execute(True)
1893 SketchPoint_1 = SketchProjection_1.createdFeature()
1894 SketchPoint_1.execute(True)
1895 sk_coo_x_1 = SketchAPI_Point(SketchPoint_1).coordinates().x()
1896 sk_coo_y_1 = SketchAPI_Point(SketchPoint_1).coordinates().y()
1898 SketchProjection_2 = sketch.addProjection(model.selection("VERTEX", nom_centre_2), False)
1899 SketchProjection_2.execute(True)
1900 SketchPoint_2 = SketchProjection_2.createdFeature()
1901 SketchPoint_2.execute(True)
1902 sk_coo_x_2 = SketchAPI_Point(SketchPoint_2).coordinates().x()
1903 sk_coo_y_2 = SketchAPI_Point(SketchPoint_2).coordinates().y()
1905 SketchProjection_3 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1906 SketchProjection_3.execute(True)
1907 SketchLine_0 = SketchProjection_3.createdFeature()
1908 SketchLine_0.execute(True)
1910 # 6.2. Lignes perpendiculaires à l'axe passant par les centres
1911 SketchLine_1 = sketch.addLine(sk_coo_x_1, sk_coo_y_1, sk_coo_x_1+rayon_1, sk_coo_y_1)
1912 SketchLine_1.execute(True)
1913 SketchLine_1.setAuxiliary(True)
1914 contrainte = sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.startPoint())
1915 contrainte.execute(True)
1916 contrainte = sketch.setPerpendicular(SketchLine_0.result(), SketchLine_1.result())
1917 contrainte.execute(True)
1918 contrainte = sketch.setLength(SketchLine_1.result(), nom_par_1)
1919 contrainte.execute(True)
1921 SketchLine_2 = sketch.addLine(sk_coo_x_2, sk_coo_y_2, sk_coo_x_2+rayon_2, sk_coo_y_2)
1922 SketchLine_2.execute(True)
1923 SketchLine_2.setAuxiliary(True)
1924 contrainte = sketch.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_2.startPoint())
1925 contrainte.execute(True)
1926 contrainte = sketch.setPerpendicular(SketchLine_0.result(), SketchLine_2.result())
1927 contrainte.execute(True)
1928 contrainte = sketch.setLength(SketchLine_2.result(), nom_par_2)
1929 contrainte.execute(True)
1931 # 6.3. Ligne joignant les extrémités des précédentes et point milieu
1932 SketchLine_3 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
1933 SketchLine_3.execute(True)
1934 contrainte = sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_1.endPoint())
1935 contrainte.execute(True)
1936 contrainte = sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_2.endPoint())
1937 contrainte.execute(True)
1938 SketchLine_3.setAuxiliary(True)
1939 SketchPoint_3 = sketch.addPoint(sk_coo_x_1, sk_coo_y_1)
1940 SketchPoint_3.execute(True)
1941 contrainte = sketch.setMiddlePoint(SketchLine_3.result(), SketchPoint_3.coordinates())
1942 contrainte.execute(True)
1944 # 6.4. Ligne support de la future révolution
1945 SketchLine_4 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
1946 SketchLine_4.execute(True)
1947 contrainte = sketch.setMiddlePoint(SketchLine_4.result(), SketchPoint_3.coordinates())
1948 contrainte.execute(True)
1949 contrainte = sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_4.result())
1950 contrainte.execute(True)
1951 contrainte = sketch.setLength(SketchLine_4.result(), "1.2*{}".format(nom_par_3))
1952 contrainte.execute(True)
1956 nom_sketch = "{}_esquisse".format(self.nom_solide)
1957 exec_nom (sketch,nom_sketch)
1959 # 7. Création du cone complet
1960 nom_cone = "{}_cone".format(self.nom_solide)
1961 self._cree_revolution ( nom_sketch, nom_centre_1, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
1963 # 8. Intersection de la face conique avec le solide initial
1964 face = self._creation_face_inter ( nom_cone )
1968 #=========================== Fin de la méthode ==================================
1970 #=========================== Début de la méthode =================================
1972 def _cree_centre_axe_plan ( self, coo_c, vect, prefixe, n_recur ):
1973 """Crée un centre, un axe, un plan
1976 :coo_c: coordonnées du centre de la base
1977 :vect: coordonnées du vecteur
1978 :prefix: prefixe du nom des objets
1979 :n_recur: niveau de récursivité
1983 :normal: vecteur normal
1987 nom_fonction = __name__ + "/_cree_centre_axe_plan"
1988 blabla = "Dans {} :".format(nom_fonction)
1989 if self._verbose_max:
1990 print_tab (n_recur, blabla)
1991 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1992 print_tab (n_recur, "Normale : ({}, {}, {})".format(vect[0], vect[1], vect[2]))
1994 # Création du point central
1995 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1996 nom_centre = "{}_centre".format(prefixe)
1997 exec_nom (centre,nom_centre)
1998 if self.fonction_0 is None:
1999 self.fonction_0 = centre
2001 # Création du vecteur
2002 vecteur = model.addAxis(self.part_doc, vect[0], vect[1], vect[2])
2003 nom_vect = "{}_vecteur".format(prefixe)
2004 exec_nom (vecteur,nom_vect)
2006 # Création du plan perpendiculaire au vecteur normal
2007 plan = model.addPlane(self.part_doc, model.selection("EDGE", vecteur.name()), model.selection("VERTEX", centre.name()), True)
2008 nom_plan = "{}_plan".format(prefixe)
2009 exec_nom (plan,nom_plan)
2011 #print ("fin de {}".format(nom_fonction))
2013 return centre, vecteur, plan
2015 #=========================== Fin de la méthode ==================================
2017 #=========================== Début de la méthode =================================
2019 def _calcul_lg_caract ( self, objet, n_recur ):
2020 """Crée une longueur caractéristique de l'objet
2023 :objet: l'objet à traiter
2024 :n_recur: niveau de récursivité
2027 :l_caract: longueur caractéristique de l'objet
2030 nom_fonction = __name__ + "/_calcul_lg_caract"
2031 blabla = "Dans {} :".format(nom_fonction)
2033 if self._verbose_max:
2034 print_tab (n_recur, blabla)
2036 properties = model.getGeometryCalculation(self.part_doc,model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
2037 l_caract = properties[0]
2039 if self._verbose_max:
2040 print_tab (n_recur, "Longueur caractéristique : ", l_caract)
2044 #=========================== Fin de la méthode ==================================
2046 #=========================== Début de la méthode =================================
2048 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
2049 """Crée un volume de révolution
2052 :nom_sketch: nom de l'esquisse à révolutionner
2053 :nom_centre: nom du point associé au centre du volume de révolution
2054 :coo_x, coo_y, coo_z: coordonnées du centre du tore
2055 :axe_x, axe_y, axe_z: coordonnées de l'axe
2056 :rayon_1 : rayon principal
2057 :rayon_2 : rayon secondaire
2058 :nom_objet: nom de l'objet 2D créé
2061 nom_fonction = __name__ + "/_cree_revolution"
2062 blabla = "Dans {} :\n".format(nom_fonction)
2064 if self._verbose_max:
2066 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2067 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2070 # Création d'un point décalé par rapport au point central
2071 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
2072 nom_point = "{}_point".format(self.nom_solide)
2073 exec_nom (point,nom_point)
2075 # Création de l'axe de la rotation
2076 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
2077 nom_axe_r = "{}_axe_r".format(self.nom_solide)
2078 exec_nom (axe_r,nom_axe_r)
2080 # Création de l'objet complet
2081 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
2082 exec_nom (objet, nom_objet, (85, 0, 255))
2084 #=========================== Fin de la méthode ==================================
2086 #=========================== Début de la méthode =================================
2088 def _creation_face_surface ( self, nom_objet, suffixe ):
2089 """Crée la face qui est la surface externe d'un objet
2091 . Crée le groupe de la face externe
2092 . Transforme le groupe en face résultat
2095 :nom_objet: nom de l'objet 3D à traiter
2096 :suffixe: suffixe pour nommer l'objet 2D
2097 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2100 :objet_2d: l'objet 2D support de la face externe de l'objet 3D
2103 nom_fonction = __name__ + "/_creation_face_inter"
2104 blabla = "Dans {} :\n".format(nom_fonction)
2106 if self._verbose_max:
2109 # 1. Le groupe de la surface
2110 groupe = model.addGroup(self.part_doc, "Faces", [model.selection("FACE", "{}/Face_1".format(nom_objet))])
2111 nom = "{}_{}_groupe".format(self.nom_solide,suffixe)
2112 exec_nom (groupe, nom, (85, 0, 255))
2114 # 2. Création de la face en surface
2115 objet_2d = model.addGroupShape(self.part_doc, [model.selection("COMPOUND", nom)])
2116 nom = "{}_{}".format(self.nom_solide,suffixe)
2117 exec_nom (objet_2d, nom, (85, 0, 255))
2121 #=========================== Fin de la méthode ==================================
2123 #=========================== Début de la méthode =================================
2125 def _creation_face_inter ( self, nom_objet, nom_solide=None ):
2126 """Crée la face par intersection entre l'objet initial et une face complète
2128 . Repère la face principale de l'objet support
2129 . Réalise l'intersection avec le solide initial
2132 :nom_objet: nom de l'objet 2D créé
2133 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2136 :face: la face externe de l'objet support intersecté avec le solide initial
2139 nom_fonction = __name__ + "/_creation_face_inter"
2140 blabla = "Dans {} :\n".format(nom_fonction)
2142 if self._verbose_max:
2145 if nom_solide is None:
2146 nom_solide = self.nom_solide_aux
2148 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_objet)], keepSubResults = True)
2153 #=========================== Fin de la méthode ==================================
2155 #=========================== Début de la méthode =================================
2157 def face_mediane_solide (self, solide, n_recur=0):
2158 """Calcul de la face médiane pour un solide
2161 :solide: solide SHAPER à traiter
2162 :n_recur: niveau de récursivité
2165 :erreur: code d'erreur
2166 :message: message d'erreur
2169 nom_fonction = __name__ + "/face_mediane_solide"
2170 blabla = "Dans {} :".format(nom_fonction)
2172 if self._verbose_max:
2173 print_tab (n_recur, blabla, saut_av=True)
2175 print_tab (n_recur, "Traitement du solide ", solide.name())
2184 # 2. Calcul des caractéristiques géométriques des faces
2186 tb_caract = self._calcul_caract_faces ( solide, n_recur )
2188 # 3. Tri des faces en fonction de leurs caractéristiques géométriques
2190 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract, n_recur )
2194 # 4. Création de la face médiane
2196 erreur, face = self._cree_face_mediane ( solide, caract_face_1, caract_face_2, n_recur )
2197 if ( erreur or ( face is None ) ):
2200 # 6. Exportation step
2202 if self._export_step:
2203 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2204 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2205 export.execute(True)
2212 if ( erreur and self._verbose_max ):
2213 print (blabla, message)
2215 return erreur, message
2217 #=========================== Fin de la méthode ==================================
2219 #=========================== Début de la méthode =================================
2221 def _traitement_objet (self, solide, n_recur=0):
2222 """Traitement d'un objet
2225 :solide: solide SHAPER à traiter
2226 :n_recur: niveau de récursivité
2229 :erreur: code d'erreur
2230 :message: message d'erreur
2233 nom_fonction = __name__ + "/_traitement_objet"
2234 blabla = "Dans {} :".format(nom_fonction)
2236 if self._verbose_max:
2237 print_tab (n_recur, blabla, saut_av=True)
2238 texte = "solide = {} ".format(solide.name())
2239 print_tab (n_recur, texte, solide)
2241 # 1. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2242 # Attention à ne pas recréer le répertoire à chaque fois
2243 if self._export_step:
2245 if self.rep_step is None:
2247 if self._verbose_max:
2248 print_tab (n_recur, "Préparation de l'export STEP")
2250 if self.ficcao is None:
2251 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2253 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2254 if os.path.isdir(self.rep_step):
2255 l_aux = os.listdir(self.rep_step)
2256 for nomfic in l_aux:
2257 os.remove(os.path.join(self.rep_step,nomfic))
2259 os.mkdir(self.rep_step)
2261 if self._verbose_max:
2262 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2264 # 2. Calcul réel de la face médiane
2266 erreur, message = self.face_mediane_solide (solide, n_recur)
2268 return erreur, message
2270 #=========================== Fin de la méthode ==================================
2272 #=========================== Début de la méthode =================================
2274 def surf_fic_cao (self, ficcao, nom_objet=None):
2275 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2278 :ficcao: fichier de l'objet à traiter
2279 :nom_objet: un nom à donner à l'objet à traiter
2282 :erreur: code d'erreur
2283 :message: message d'erreur
2286 nom_fonction = __name__ + "/surf_fic_cao"
2287 blabla = "Dans {} :".format(nom_fonction)
2289 if self._verbose_max:
2299 if self.affiche_aide_globale:
2302 # 1. Définition de la pièce
2304 self.part_doc = model.activeDocument()
2305 if ( self.part_doc.kind() == "PartSet" ):
2306 part = model.addPart(self.part_doc)
2307 self.part_doc = part.document()
2309 # 2. Import de la CAO
2311 self.ficcao = ficcao
2312 print ("Traitement du fichier {}".format(ficcao))
2314 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2318 # 3. Calcul des surfaces
2320 erreur, message = self.surf_objet_shaper ( objet )
2327 if ( erreur and self._verbose_max ):
2328 print (blabla, message)
2330 return erreur, message
2332 #=========================== Fin de la méthode ==================================
2334 #=========================== Début de la méthode =================================
2336 def surf_objet_shaper (self, objet):
2337 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2340 :objet: objet à traiter
2343 :erreur: code d'erreur
2344 :message: message d'erreur
2347 nom_fonction = __name__ + "/surf_objet_shaper"
2348 blabla = "Dans {} :".format(nom_fonction)
2350 if self._verbose_max:
2358 if self.affiche_aide_globale:
2361 # 1. Acquisition de la liste des noms des sous-objets solides
2363 self.d_statut_so = dict()
2364 self.l_noms_so = list()
2365 self.l_faces_m = list()
2367 _ = self._nom_sous_objets (objet, True)
2368 if self._verbose_max:
2369 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2371 # 2. Les faces médianes
2373 erreur, message = self._surf_objet_shaper_0 ( objet )
2377 # 3. Gestion des faces créées
2379 self._surf_objet_shaper_1 ( )
2381 # 4. Futur message pour le résultat
2383 if ( self._export_step and not erreur ):
2384 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2388 return erreur, message
2390 #=========================== Fin de la méthode ==================================
2392 #=========================== Début de la méthode =================================
2394 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2395 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2398 :objet: objet à traiter
2399 :n_recur: niveau de récursivité
2402 :erreur: code d'erreur
2403 :message: message d'erreur
2406 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2407 blabla = "Dans {} :".format(nom_fonction)
2409 if self._verbose_max:
2410 print_tab (n_recur, blabla)
2411 print_tab (n_recur, "n_recur = ", n_recur)
2418 # 1. Au premier passage, il faut récupérer la pièce SHAPER et garder la référence au résultat principal
2420 if ( n_recur == 0 ):
2421 self.part_doc = model.activeDocument()
2422 objet_0 = objet.result()
2423 self.objet_principal = objet_0
2424 objet_bis = objet.defaultResult().shape()
2425 if self._verbose_max:
2426 print_tab (0, "Examen de l'objet initial ", objet.result().name(), saut_av=True)
2427 print_tab (0, "Type python : ", type(objet))
2428 print_tab (0, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2431 if self._verbose_max:
2432 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2433 print_tab (n_recur, "Type python : ", type(objet))
2434 print_tab (n_recur, "shapeType : ", objet.shapeType())
2436 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2438 nb_sub_results = objet_0.numberOfSubs()
2440 if self._verbose_max:
2441 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType(), saut_av=True)
2442 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2444 for n_sobj in range(nb_sub_results):
2446 # 2.1. Exploration récursive de l'arborescence
2448 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2455 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2457 if ( objet_0.shapeType() == "SOLID" ):
2458 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2462 # 3. Futur message pour le résultat
2464 if self._export_step:
2465 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2469 return erreur, message
2471 #=========================== Fin de la méthode ==================================
2473 #=========================== Début de la méthode =================================
2475 def _surf_objet_shaper_1 (self, n_recur=0):
2476 """Gestion des surfaces médianes créées
2479 :n_recur: niveau de récursivité
2482 :erreur: code d'erreur
2483 :message: message d'erreur
2486 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2487 blabla = "Dans {} :\n".format(nom_fonction)
2489 if self._verbose_max:
2490 print_tab (n_recur, blabla)
2492 # 1. Informations sur les faces à problème
2494 if self.faces_pb_nb:
2495 if ( self.faces_pb_nb == 1 ):
2496 texte = "1 face pose"
2498 texte = "{} faces posent".format(self.faces_pb_nb)
2499 print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2501 # 2. Si plus d'une face a été créée
2502 if ( len(self.l_faces_m) > 1 ):
2504 # 2.1. Partition du paquet de faces
2506 if self._verbose_max:
2507 print_tab (n_recur, "Partitionnnement des faces créées.")
2509 # 2.1.1. Pour une raison mystérieuse, il faut commencer par les faces entières, puis mettre les sous-faces éventuelles
2511 for (face,_) in self.l_faces_m:
2512 if not face.result().numberOfSubs():
2513 d_faces[face.name()] = [face.name()]
2514 for (face,_) in self.l_faces_m:
2515 nb_sub_results = face.result().numberOfSubs()
2518 for n_sobj in range(nb_sub_results):
2519 laux.append(face.result().subResult(n_sobj).name())
2520 d_faces[face.name()] = laux
2523 for _, laux in d_faces.items():
2524 for s_face_n in laux:
2525 l_objets.append(model.selection("FACE", s_face_n))
2527 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2528 nom = "{}_M".format(self.objet_principal.name())
2529 exec_nom (Partition_1,nom)
2532 for face_n, laux in d_faces.items():
2533 Partition_1.result().subResult(iaux).setName("{}".format(face_n))
2534 if ( len(laux) > 1 ):
2535 for jaux, s_face_n in enumerate(laux):
2536 Partition_1.result().subResult(iaux).subResult(jaux).setName("{}_M".format(s_face_n))
2538 couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
2540 # 2.2. Récupération des faces individuelles
2542 if self._verbose_max:
2543 print_tab (n_recur, "Récupération des faces individuelles.")
2546 for iaux, (face,_) in enumerate(self.l_faces_m):
2547 l_objets.append(face.result())
2549 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2550 exec_nom (Recover_1)
2551 for iaux, (face,_) in enumerate(self.l_faces_m):
2552 Recover_1.results()[iaux].setName("{}".format(face.name()))
2553 Recover_1.results()[iaux].setColor(0, 170, 0)
2554 nb_sub_results = Recover_1.results()[iaux].numberOfSubs()
2555 for n_sobj in range(nb_sub_results):
2556 Recover_1.results()[iaux].subResult(n_sobj).setName("{}_{}".format(face.name(),n_sobj))
2557 Recover_1.results()[iaux].subResult(n_sobj).setColor(0, 170, 0)
2559 # 3. Mise en dossier
2561 if self._verbose_max:
2562 print_tab (n_recur, "Mise en dossier.")
2564 for (face,fonction_0) in self.l_faces_m:
2565 if fonction_0 is not None:
2566 nom = face.name()[:-2]
2567 if self._verbose_max:
2568 print ( "Dossier {} de {} à {}".format(nom,fonction_0.name(),face.name()))
2569 dossier = model.addFolder(self.part_doc, fonction_0, face)
2570 dossier.setName(nom)
2572 if ( len(self.l_faces_m) > 1 ):
2574 nom = self.objet_principal.name()
2575 if self._verbose_max:
2576 print ( "Dossier {} de {} à {}".format(nom,Partition_1.name(),Recover_1.name()))
2577 dossier = model.addFolder(self.part_doc, Partition_1, Recover_1)
2578 dossier.setName(nom)
2580 #=========================== Fin de la méthode ==================================
2582 #=========================== Début de la méthode =================================
2584 def surf_solide_shaper (self, solide, n_recur):
2585 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2588 :solide: solide SHAPER à traiter
2589 :n_recur: numéro de la récurrence
2592 :erreur: code d'erreur
2593 :message: message d'erreur
2596 nom_fonction = __name__ + "/surf_solide_shaper"
2597 blabla = "Dans {} :".format(nom_fonction)
2599 if self._verbose_max:
2600 print_tab (n_recur, blabla, saut_av=True)
2607 self.nom_solide = solide.name()
2608 if self._verbose_max:
2609 print_tab (n_recur, "solide : ", self.nom_solide)
2611 # 1. Isolement du solide
2612 solide_aux, recover = self._isole_solide ( solide, n_recur )
2614 # 2. Traitement de l'objet correspondant
2615 erreur, message = self._traitement_objet ( solide_aux, n_recur=n_recur )
2617 if ( erreur and self._verbose_max ):
2618 print (blabla, message)
2620 # 3. Neutralisation des erreurs dues à l'épaisseur
2621 if ( erreur in (-2,-1,2) ):
2627 # 4. Mise en forme de l'objet principal récupéré
2628 if ( recover is not None ):
2629 _ = self._nom_sous_objets (recover, False)
2633 return erreur, message
2635 #=========================== Fin de la méthode ==================================
2637 #========================== Fin de la classe ====================================