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.21"
41 #========================= Les imports - Début ===================================
52 from SketchAPI import *
53 from salome.shaper import model
54 from salome.shaper import geom
56 from GeomAlgoAPI import *
60 #========================== Les imports - Fin ====================================
63 D_FMT["stp"] = ["stp", "step"]
64 D_FMT["igs"] = ["igs", "iges"]
65 for CLE in ("brep", "xao"):
68 # statut = 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
87 # Transparence des solides traités correctement
90 # Limite basse de l'épaisseur pour pouvoir faire les intersections
93 #========================= Début de la fonction ==================================
95 def decode_cao (fmt_cao):
96 """Décode le format de la cao
99 :fmt_cao: format du fichier, step, iges, etc.
101 :fmt_cao_0: format décodé
106 fmt_cao_low = fmt_cao.lower()
108 for cle, l_aux in D_FMT.items():
109 if ( fmt_cao_low in l_aux ):
115 #========================= Fin de la fonction ===================================
117 #========================= Début de la fonction ==================================
119 def import_cao (part_doc, ficcao, nom_objet=None, verbose=False):
120 """Importation d'une cao
124 :ficcao: le fichier de la CAO
125 :nom_objet: nom à donner à l'objet lu, éventuellement
127 :objet: l'objet importé dans SHAPER
130 nom_fonction = __name__ + "/import_cao"
131 blabla = "Dans {} :\n".format(nom_fonction)
132 message_0 = "Fichier : {}\n".format(ficcao)
134 message = blabla + message_0
135 message += "nom_objet : {}".format(nom_objet)
143 laux = ficcao.split(".")
144 fmt_cao_0 = decode_cao (laux[-1])
146 if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
147 message += "Le format de CAO est inconnu"
151 message += "Le fichier de CAO n'a pas été décodé correctement."
154 elif not os.path.isfile(ficcao):
155 message += "Le fichier de CAO est inconnu."
161 objet = model.addImport(part_doc, ficcao)
162 exec_nom (objet, nom_objet)
166 texte = "Objet : '{}'\n".format(objet.result().name())
167 texte += "De type : '{}'".format(objet.result().shapeType())
170 return erreur, message, objet
172 #========================= Fin de la fonction ===================================
174 #========================= Début de la fonction ==================================
176 def couleur_objet (objet, n_recur=0, coul_r=1, coul_g=0, coul_b=0, verbose=False):
177 """Appliquer une couleur à un objet et à ses sous_objets
180 :objet: objet à traiter
181 :n_recur: niveau de récursivité
182 :coul_r,coul_g,coul_b: code RGB de la couleur à appliquer
185 :rang: rang du sous-objet
188 nom_fonction = __name__ + "/couleur_objet"
189 blabla = "Dans {} :".format(nom_fonction)
193 print ("n_recur = {}".format(n_recur))
194 print_tab(n_recur, "objet : ", objet.name())
195 print_tab(n_recur, "RGB = ({},{},{})".format(coul_r,coul_g,coul_b))
197 # 1. Au premier passage, il faut garder la référence au résultat principal
200 objet_0 = objet.result()
204 #print (dir(objet_0))
206 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
208 nb_sub_results = objet_0.numberOfSubs()
211 print_tab(n_recur, "Examen de l'objet",objet_0.name())
212 texte = "Formé de {} sous-objets".format(nb_sub_results)
213 print_tab(n_recur, texte)
215 for n_sobj in range(nb_sub_results):
217 # 2.1. Exploration récursive de l'arborescence
219 couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b, verbose )
221 # 2.2. Cet objet n'a pas de sous-objets : on le colore
223 print_tab(n_recur, "Couleur affectée à l'objet ",objet_0.name())
224 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
226 #print ("sortie de {}".format(nom_fonction))
228 #========================= Fin de la fonction ===================================
230 #========================= Début de la fonction ==================================
232 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
233 """Imprime avec des tabulations
236 :nb_tab: nombre de tabulations à appliquer
237 :message: message principal
238 :argu: argument du format
239 :saut_av: saut de ligne avant le texte
240 :saut_ap: saut de ligne après le texte
248 for _ in range(nb_tab):
252 if ( argu is not None ):
253 texte += "{}".format(argu)
260 #========================= Fin de la fonction ===================================
262 #========================= Début de la fonction ==================================
264 def nommage (objet, nom, couleur=None):
265 """Nomme un objet et son résultat
268 :objet: objet à traiter
269 :nom: nom à attribuer
270 :couleur: éventuellement couleur
274 objet.result().setName(nom)
276 if ( couleur is not None ):
277 objet.result().setColor(couleur[0], couleur[1], couleur[2])
279 #========================= Fin de la fonction ===================================
281 #========================= Début de la fonction ==================================
283 def exec_nom (fonction, nom=None, couleur=None):
284 """Exécute la fonction puis éventuellement la nomme et nomme son résultat ; Couleur éventuelle
286 Attention : il faut commencer par exécuter la fonction sinon l enommage n'est pas cohérent en mode macro. Mystère...
289 :fonction: fonction à traiter
290 :nom: nom à attribuer éventuellement
291 :couleur: éventuellement couleur
294 fonction.execute(True)
296 if ( nom is not None ):
297 nommage (fonction, nom, couleur)
299 #========================= Fin de la fonction ===================================
302 #=================================== La classe ===================================
304 class SurfaceMediane (object):
306 """Calcul des surfaces médianes de solides minces
308 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
309 une structure qui est un solide ou un assemblage de solides (compound).
310 Pour réaliser l'opération, trois façons de faire :
312 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
314 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
315 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
317 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
318 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
321 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
322 de taille identique et supérieure aux tailles des autres faces du solide. \
323 Cela fonctionne pour des surfaces planes ou de forme canonique.
324 Il crée alors une surface au milieu de ces deux grandes faces. \
325 Cette face est coloriée en vert, le solide est en vert et transparent.
327 On sait traiter les faces :
334 Si la création n'a pas eu lieu, un message est émis et les solides sont mis en couleur :
335 . Rouge : le solide n'est pas assez mince.
336 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
337 . Orange : la forme de la face n'est pas reconnue.
345 . Exportation finale dans un fichier step. Par défaut, pas d'export.
346 -export_step/-no_export_step
349 surf_fic_cao --> import_cao
350 --> surf_objet_shaper (récursif) --> _nom_sous_objets
351 --> _surf_objet_shaper_0
352 --> surf_solide_shaper --> _isole_solide --> _isole_solide_a
354 --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
356 --> _cree_face_mediane
358 _cree_face_mediane --> _cree_face_mediane_plane
359 --> _cree_face_mediane_cylindre
360 --> _cree_face_mediane_sphere
361 --> _cree_face_mediane_tore
362 --> _cree_face_mediane_cone
363 --> _cree_face_mediane_0
372 affiche_aide_globale = 0
379 nom_solide_aux = None
385 objet_principal = None
386 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
388 # Statut de chaque sous-objet connu par son nom :
389 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
391 # Liste des faces médianes créées et des fonctions initiales
393 # La fonction initiale
399 #=========================== Début de la méthode =================================
401 def __init__ ( self, liste_option ):
403 """Le constructeur de la classe SurfaceMediane
405 Décodage des arguments
406 On cherche ici les arguments généraux : aide, verbeux
409 for option in liste_option :
412 if isinstance(option,str):
413 saux = option.upper()
415 if saux in ( "-H", "-HELP" ):
416 self.affiche_aide_globale = 1
419 elif saux == "-VMAX" :
421 self._verbose_max = 1
422 elif saux == "-EXPORT_STEP":
423 self._export_step = True
424 elif saux == "-NO_EXPORT_STEP":
425 self._export_step = False
427 #=========================== Fin de la méthode ==================================
429 #=========================== Début de la méthode =================================
432 """A la suppression de l'instance de classe"""
433 if self._verbose_max:
434 print ("Suppression de l'instance de la classe.")
436 #=========================== Fin de la méthode ==================================
438 #=========================== Début de la méthode =================================
440 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
441 """Gère les noms des sous_objets solides
444 :objet: objet à traiter
445 :lecture: vrai pour lire les noms, faux pour les attribuer
446 :n_recur: niveau de récursivité
447 :rang: rang du sous-objet
450 :rang: rang du sous-objet
453 nom_fonction = __name__ + "/_nom_sous_objets"
454 blabla = "Dans {} :\n".format(nom_fonction)
456 if self._verbose_max:
458 for _ in range(n_recur):
460 texte = "\n{}{}".format(prefixe,blabla)
461 texte += "{}n_recur = {}".format(prefixe,n_recur)
462 texte += "\n{}lecture = {}".format(prefixe,lecture)
465 # 1. Au premier passage, il faut garder la référence au résultat principal
468 objet_0 = objet.result()
469 if self._verbose_max:
470 print ("d_statut_so = {}".format(self.d_statut_so))
474 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
476 nb_sub_results = objet_0.numberOfSubs()
478 if self._verbose_max:
479 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
480 texte += "de type '{}'".format(objet_0.shapeType())
481 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
484 for n_sobj in range(nb_sub_results):
486 # 2.1. Exploration récursive de l'arborescence
488 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
490 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
492 if ( objet_0.shapeType() == "SOLID" ):
493 # A la lecture, on enregistre le nom
496 self.l_noms_so.append(nom)
497 self.d_statut_so[nom] = 0
498 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
500 nom = self.l_noms_so[rang]
502 etat = self.d_statut_so[nom]
503 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
505 objet_0.setTransparency (TRANSPARENCE)
510 #=========================== Fin de la méthode ==================================
512 #=========================== Début de la méthode =================================
514 def _isole_solide ( self, solide, n_recur ):
515 """Isole le solide de son arboresence
518 :solide: le solide à traiter
519 :n_recur: numéro de la récurrence
522 :objet: le solide isolé
523 :recover: la fonction de récupération
526 nom_fonction = __name__ + "/_isole_solide"
527 blabla = "Dans {} :".format(nom_fonction)
528 if self._verbose_max:
529 print_tab (n_recur, blabla)
530 texte = "Pour le solide '{}' ".format(solide.name())
531 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
532 print_tab (n_recur, texte)
534 if ( solide.name() != self.objet_principal.name() ):
535 objet, recover = self._isole_solide_a ( solide, n_recur )
538 objet, recover = self._isole_solide_b ( solide, n_recur )
540 if self._verbose_max:
541 print_tab (n_recur, "objet final : ", objet.name())
542 print_tab (n_recur, "fonction_0 : {}".format(self.fonction_0))
543 print_tab (n_recur, "recover : {}".format(recover))
545 return objet, recover
547 #=========================== Fin de la méthode ==================================
549 #=========================== Début de la méthode =================================
551 def _isole_solide_a ( self, solide, n_recur ):
552 """Isole le solide de son arboresence
555 :solide: le solide à traiter
556 :n_recur: numéro de la récurrence
559 :objet: le solide isolé
560 :recover: la fonction de récupération
563 nom_fonction = __name__ + "/_isole_solide_a"
564 blabla = "Dans {} :".format(nom_fonction)
565 if self._verbose_max:
566 print_tab (n_recur, blabla)
567 texte = "Pour le solide '{}' ".format(solide.name())
568 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
569 print_tab (n_recur, texte)
571 if self._verbose_max:
572 print_tab (n_recur, ". Extraction du solide '{}'".format(self.objet_principal.name()))
574 # 1. Extraction du solide
575 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
576 #exec_nom (remove_subshapes)
577 #print ('remove_subshapes = model.addRemoveSubShapes(part_doc, model.selection("COMPOUND", "{}"))'.format(self.objet_principal.name()))
578 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
579 #print ('remove_subshapes.setSubShapesToKeep([model.selection("SOLID", "{}")])'.format(solide.name()))
580 #exec_nom (remove_subshapes)
582 self.nom_solide_aux = "{}_S".format(solide.name())
583 if self._verbose_max:
584 print_tab (n_recur, "\tAttribution à remove_subshapes.result() du nom '{}'".format(self.nom_solide_aux))
585 exec_nom (remove_subshapes,self.nom_solide_aux)
587 self.fonction_0 = remove_subshapes
589 # 2. Récupération de l'objet principal
590 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
591 if self._verbose_max:
592 print_tab (n_recur, "\tAttribution à recover du nom '{}'".format(self.objet_principal.name()))
593 exec_nom (recover,self.objet_principal.name())
595 return remove_subshapes.result(), recover
597 #=========================== Fin de la méthode ==================================
599 #=========================== Début de la méthode =================================
601 def _isole_solide_b ( self, solide, n_recur ):
602 """Isole le solide de son arboresence
605 :solide: le solide à traiter
606 :n_recur: numéro de la récurrence
609 :objet: le solide isolé
610 :recover: la fonction de récupération
613 nom_fonction = __name__ + "/_isole_solide_b"
614 blabla = "Dans {} :".format(nom_fonction)
615 if self._verbose_max:
616 print_tab (n_recur, blabla)
617 texte = "Pour le solide '{}' ".format(solide.name())
618 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
619 print_tab (n_recur, texte)
621 if self._verbose_max:
622 print_tab (n_recur, ". Mise en place du solide")
624 self.nom_solide_aux = self.objet_principal.name()
625 self.fonction_0 = None
629 #=========================== Fin de la méthode ==================================
631 #=========================== Début de la méthode =================================
633 def _faces_du_solide ( self, solide, n_recur=0 ):
634 """Détermine les faces d'un solide
637 :solide: solide SHAPER à traiter
638 :n_recur: niveau de récursivité
641 :l_faces_car: pour chaque face du solide (surface,caractéristiques)
644 nom_fonction = __name__ + "/_faces_du_solide"
645 blabla = "Dans {} :".format(nom_fonction)
646 if self._verbose_max:
647 print_tab (n_recur, blabla, saut_av=True)
651 if self._verbose_max:
652 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
653 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
656 #print_tab (n_recur, "volume = ", GeomAlgoAPI_ShapeTools.volume(solide.shape()))
657 # 1. Repérage des faces
658 objResult = solide.resultSubShapePair()[0]
660 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
662 l_faces.append(exp.current().face())
667 for iface, face in enumerate(l_faces):
668 surf = GeomAlgoAPI_ShapeTools.area(face)
669 caract = geom.shapeInfo(face)
670 if self._verbose_max:
671 print_tab (n_recur, "\tFace n°{} ; ".format(iface), "surface = {}, caractéristiques = {}".format(surf,caract))
672 l_faces_car.append((surf,caract))
676 #=========================== Fin de la méthode ==================================
678 #=========================== Début de la méthode =================================
680 def _calcul_caract_faces ( self, solide, n_recur ):
681 """Calcule les caractéristiques géométriques des faces du solide
684 :solide: solide SHAPER à traiter
685 :n_recur: niveau de récursivité
688 :tb_caract: tableau des caractéristiques géométriques des faces
691 nom_fonction = __name__ + "/_calcul_caract_faces"
692 blabla = "Dans {} :".format(nom_fonction)
693 if self._verbose_max:
694 print_tab (n_recur, blabla, saut_av=True)
695 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
696 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
698 # 1. Repérage des faces
699 objResult = solide.resultSubShapePair()[0]
701 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
703 l_faces.append(exp.current().face())
706 # 2. Caractéristiques
707 nb_faces = len(l_faces)
708 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
709 for iaux, face in enumerate(l_faces):
710 surf = GeomAlgoAPI_ShapeTools.area(face)
711 caract = geom.shapeInfo(face)
712 if self._verbose_max:
713 print_tab (n_recur, "\tFace n°{} ; ".format(iaux), "surface = {}, caractéristiques = {}".format(surf,caract))
715 tb_caract [iaux][0] = face
716 tb_caract [iaux][1] = surf
717 tb_caract [iaux][2] = caract
719 #if self._verbose_max:
720 #for iaux in range(nb_faces):
721 #print ("\t. tb_caract : {} {}".format(surf,tb_caract[iaux][2]))
725 #=========================== Fin de la méthode ==================================
727 #=========================== Début de la méthode =================================
729 def _tri_faces ( self, tb_caract, n_recur ):
730 """Trie les faces en fonction de leurs surfaces
733 :tb_caract: tableau des caractéristiques géométriques des faces
734 :n_recur: niveau de récursivité
737 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
743 nom_fonction = __name__ + "/_tri_faces"
744 blabla = "Dans {} :".format(nom_fonction)
746 # 1. Tri du tableau en fonction des surfaces
747 if self._verbose_max:
748 print_tab (n_recur, blabla)
749 print_tab (n_recur, "tb_caract brut : ", tb_caract)
750 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
751 if self._verbose_max:
752 print_tab (n_recur, "tb_caract trié :", tb_caract_1)
754 if self._verbose_max:
755 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
756 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
759 # 2. La surface suivante doit être différente, sinon ce n'est pas un solide mince
760 if ( len(tb_caract) > 2 ):
762 if self._verbose_max:
763 texte += "\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
765 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
766 if ( ecart < self._epsilon ):
767 message = "\nSolide '{}'\n".format(self.nom_solide)
768 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
769 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
770 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
771 if self._verbose_max:
772 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
773 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
774 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
776 self.d_statut_so[self.nom_solide] = -1
777 self.faces_pb_nb += 1
778 self.faces_pb_msg += message
780 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
782 #=========================== Fin de la méthode ==================================
784 #=========================== Début de la méthode =================================
786 def _verif_epaisseur ( self, epaisseur ):
787 """Contrôle de la validité de l'épaisseur
790 :epaisseur: épaisseur du solide
793 nom_fonction = __name__ + "/_verif_epaisseur"
794 blabla = "Dans {} :\n".format(nom_fonction)
796 if self._verbose_max:
798 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
799 texte += ". EP_MIN : {}".format(EP_MIN)
802 if ( epaisseur <= EP_MIN ):
803 message = "\nSolide '{}'\n".format(self.nom_solide)
804 message += ". Epaisseur : {}\n".format(epaisseur)
805 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
806 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
808 self.d_statut_so[self.nom_solide] = 2
809 self.faces_pb_nb += 1
810 self.faces_pb_msg += message
814 #print ("erreur = {}".format(erreur))
818 #=========================== Fin de la méthode ==================================
820 #=========================== Début de la méthode =================================
822 def _cree_face_mediane ( self, solide, caract_face_1, caract_face_2, n_recur ):
823 """Crée la face médiane entre deux autres
826 :solide: solide SHAPER à traiter
827 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
828 :n_recur: niveau de récursivité
831 :face: la face médiane créée
834 nom_fonction = __name__ + "/_cree_face_mediane"
835 blabla = "Dans {} :".format(nom_fonction)
837 if self._verbose_max:
838 print_tab (n_recur, blabla)
839 print_tab (n_recur, "face_1 : " ,caract_face_1)
840 print_tab (n_recur, "face_2 : " ,caract_face_2)
845 # 1. Forme de la face
846 forme = caract_face_1[2][0]
848 # 2. Traitement selon la forme de la face
850 if forme in ( "Disk" , "Plane", "Rectangle"):
851 erreur, face = self._cree_face_mediane_plane ( solide, caract_face_1, caract_face_2, n_recur )
853 # 2.2. Face cylindrique
854 elif ( forme == "Cylinder" ):
855 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
857 # 2.3. Face sphérique
858 elif ( forme == "Sphere" ):
859 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
862 elif ( forme == "Torus" ):
863 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
866 elif ( forme == "Cone" ):
867 erreur, face = self._cree_face_mediane_cone ( caract_face_1, caract_face_2, n_recur )
869 # 2.N. Face de forme inconnue
871 message = "\nSolide '{}'\n".format(self.nom_solide)
872 message += "sa face la plus grande est de forme : {}\n".format(forme)
873 message += "==> Impossible de créer la face médiane.\n"
875 self.d_statut_so[self.nom_solide] = -2
876 self.faces_pb_nb += 1
877 self.faces_pb_msg += message
879 # 3. Gestion de la face produite
882 self._cree_face_mediane_0 ( face, n_recur )
884 if self._verbose_max:
885 print_tab (n_recur, "Sortie de "+blabla)
889 #=========================== Fin de la méthode ==================================
891 #=========================== Début de la méthode =================================
893 def _cree_face_mediane_0 ( self, face, n_recur ):
894 """Gestion de la face médiane créée entre deux autres
897 :face: la face médiane créée
898 :n_recur: niveau de récursivité
901 nom_fonction = __name__ + "/_cree_face_mediane_0"
902 blabla = "Dans {} :".format(nom_fonction)
904 if self._verbose_max:
905 print_tab (n_recur, blabla)
908 nom_face = self.nom_solide+"_M"
909 if self._verbose_max:
910 print_tab (n_recur,"Nom de la face créée : ", nom_face)
911 #if ( self.nom_solide_aux != self.objet_principal.name() ):
913 nommage (face, nom_face)
915 # 2. Mémorisation de la face et de la fonction initiale
916 self.l_faces_m.append((face, self.fonction_0))
918 # 3. Couleur verte pour la face
919 couleur_objet (face, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
921 # 4. Changement de statut pour le solide
922 self.d_statut_so[self.nom_solide] = 1
924 if self._verbose_max:
925 print_tab (n_recur, "Sortie de _cree_face_mediane_0")
927 #=========================== Fin de la méthode ==================================
929 #=========================== Début de la méthode =================================
931 def _cree_face_mediane_plane ( self, solide, caract_face_1, caract_face_2, n_recur ):
932 """Crée la face médiane entre deux autres - cas des surfaces planes
935 :solide: l'objet solide à traiter
936 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
937 :n_recur: niveau de récursivité
940 :face: la face médiane
943 nom_fonction = __name__ + "/_cree_face_mediane_plane"
944 blabla = "Dans {} :".format(nom_fonction)
945 if self._verbose_max:
946 print_tab (n_recur, blabla)
948 # Caractéristiques des surfaces
949 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 )
951 # Contrôle de la validité de l'épaisseur
952 erreur = self._verif_epaisseur ( d_face_1_2 )
954 # Création de la face
956 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 )
962 #=========================== Fin de la méthode ==================================
964 #=========================== Début de la méthode =================================
966 def _cree_face_mediane_plane_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
967 """Crée la face médiane entre deux autres - cas des surfaces planes
969 Décodage des caractéristiques
972 :solide: l'objet solide à traiter
973 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
974 :n_recur: niveau de récursivité
977 :coo_x, coo_y, coo_z: coordonnées du centre de la base
978 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
979 :taille: estimation de la taille de la future face
980 :d_face_1_2: la distance entre les deux faces
983 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
984 blabla = "Dans {} :".format(nom_fonction)
986 if self._verbose_max:
987 print_tab (n_recur, blabla)
988 print_tab (n_recur, "caract_face_1 : ", caract_face_1)
989 print_tab (n_recur, "caract_face_2 : ", caract_face_2)
991 # 1. Caractéristiques de la base
992 # Coordonnées du centre de la base
993 coo_x = caract_face_1[2][1]
994 coo_y = caract_face_1[2][2]
995 coo_z = caract_face_1[2][3]
996 # Coordonnées du vecteur normal
997 vnor_x = caract_face_1[2][4]
998 vnor_y = caract_face_1[2][5]
999 vnor_z = caract_face_1[2][6]
1000 # taille : une longueur caractéristique pour être certain de tout prendre
1001 l_diag = self._calcul_lg_caract ( solide, n_recur )
1003 if self._verbose_max:
1004 print_tab (n_recur, "Taille englobante : ",taille)
1006 # 2. Distance entre les deux faces
1007 face_1 = caract_face_1[0]
1008 face_2 = caract_face_2[0]
1009 d_face_1_2 = GeomAlgoAPI_ShapeTools.minimalDistance(face_1, face_2)
1010 if self._verbose_max:
1011 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
1013 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
1015 #=========================== Fin de la méthode ==================================
1017 #=========================== Début de la méthode =================================
1019 def _cree_face_mediane_plane_1 ( self, solide, coo_c, vnor, taille, d_face_1_2, n_recur ):
1020 """Crée la face médiane entre deux autres - cas des surfaces planes
1022 Création des objets de construction et de la face médiane
1025 :solide: l'objet solide à traiter
1026 :coo_c: coordonnées du centre de la base
1027 :vnor: coordonnées du vecteur normal
1028 :taille: estimation de la taille de la future face
1029 :d_face_1_2: la distance entre les deux faces
1030 :n_recur: niveau de récursivité
1033 :face: la face médiane
1036 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
1037 blabla = "Dans {} :".format(nom_fonction)
1038 if self._verbose_max:
1039 print_tab (n_recur, blabla)
1040 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1041 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
1042 print_tab (n_recur, "Taille : ", taille)
1043 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1046 _, v_norm, plan = self._cree_centre_axe_plan ( coo_c, vnor, self.nom_solide, n_recur )
1048 # 2. Création de l'esquisse
1049 sketch = self._cree_face_mediane_plane_1_a ( plan, taille, n_recur )
1052 face = self._cree_face_mediane_plane_1_b ( solide, sketch, v_norm, d_face_1_2, n_recur )
1054 #print ("fin de {}".format(nom_fonction))
1058 #=========================== Fin de la méthode ==================================
1060 #=========================== Début de la méthode =================================
1062 def _cree_face_mediane_plane_1_a ( self, plan, taille, n_recur ):
1063 """Crée la face médiane entre deux autres - cas des surfaces planes - l'esquisse
1067 :taille: estimation de la taille de la future face
1068 :n_recur: niveau de récursivité
1074 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_a"
1075 blabla = "Dans {} :".format(nom_fonction)
1076 if self._verbose_max:
1077 print_tab (n_recur, blabla)
1078 print_tab (n_recur, "Plan : {}".format(plan.name()))
1079 print_tab (n_recur, "taille : {}".format(taille))
1081 sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1082 sketch.execute(True)
1084 ### Create SketchLine
1085 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1086 SketchLine_1.execute(True)
1088 ### Create SketchLine
1089 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1090 SketchLine_2.execute(True)
1092 ### Create SketchLine
1093 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1094 SketchLine_3.execute(True)
1096 ### Create SketchLine
1097 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1098 SketchLine_4.execute(True)
1102 nom_sketch = "{}_esquisse".format(self.nom_solide)
1103 exec_nom (sketch,nom_sketch)
1105 #print ("fin de {}".format(nom_fonction))
1109 #=========================== Fin de la méthode ==================================
1111 #=========================== Début de la méthode =================================
1113 def _cree_face_mediane_plane_1_b ( self, solide, sketch, v_norm, d_face_1_2, n_recur ):
1114 """Crée la face médiane entre deux autres - cas des surfaces planes
1116 Création de la face médiane
1119 :solide: l'objet solide à traiter
1121 :v_norm: vecteur normal
1122 :d_face_1_2: la distance entre les deux faces
1123 :n_recur: niveau de récursivité
1126 :face: la face médiane
1129 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_b"
1130 blabla = "Dans {} :".format(nom_fonction)
1131 if self._verbose_max:
1132 print_tab (n_recur, blabla)
1133 print_tab (n_recur, "Esquisse : ", sketch.name())
1134 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1136 # 1. Copie du solide pour gérer les intersections
1137 #Copy_1 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1138 Copy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1139 nom = "{}_Copy_1".format(self.nom_solide_aux)
1140 exec_nom (Copy_1,nom)
1141 if self._verbose_max:
1142 print_tab (n_recur, "Après addMultiTranslation Copy_1 de nom ", nom)
1143 nom_solide = Copy_1.result().name()
1146 Recover_1 = model.addRecover(self.part_doc, Copy_1, [solide])
1147 nom = "{}_Recover_1".format(self.nom_solide_aux)
1148 exec_nom (Recover_1,nom)
1149 if self._verbose_max:
1150 print_tab (n_recur, "Après addRecover Recover_1 de nom ", nom)
1152 # 2. Création d'une face ; on la translate d'une demi-épaisseur.
1153 for iaux in range(2):
1155 # 2.1. Création d'une face à partir du sketch et translation perpendiculaire au plan de la face
1156 # On essaie les 2 côtés alternativement car on ne sait pas lequel sera le bon
1158 d_trans = -0.5*d_face_1_2*float(2*iaux-1)
1160 face = self._cree_face_mediane_plane_2 ( sketch.name(), v_norm.name(), nom_solide, d_trans, iaux, n_recur )
1162 # 2.2. Si on est du bon côté, alors on intersecte la face avec le solide et c'est bon
1164 face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1167 # 2.3. Si l'intersection est vide, on crée une nouvelle copie du solide avant de tester l'autre côté
1169 if self._verbose_max:
1170 print_tab (n_recur, "L'intersection est vide. On essaie l'autre côté")
1172 ### Create LinearCopy
1173 #Copy_2 = model.addCopy(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(self.nom_solide_aux))], 1)
1174 Copy_2 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", Recover_1.result().name())], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1175 nom = "{}_Copy_2".format(self.nom_solide_aux)
1176 exec_nom (Copy_2,nom)
1177 if self._verbose_max:
1178 print_tab (n_recur, "Après addMultiTranslation Copy_2 de nom ", nom)
1179 nom_solide = Copy_2.result().name()
1181 #print ("fin de {}".format(nom_fonction))
1185 #=========================== Fin de la méthode ==================================
1187 #=========================== Début de la méthode =================================
1189 def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1190 """Crée la face médiane entre deux autres - cas des surfaces planes
1192 Création des objets de construction et de la face médiane
1195 :face: la face médiane
1196 :Recover_1: la récupératiuon du solide
1197 :n_recur: niveau de récursivité
1200 :face: la face médiane
1203 nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1204 blabla = "Dans {} :".format(nom_fonction)
1205 if self._verbose_max:
1206 print_tab (n_recur, blabla)
1207 print_tab (n_recur, "face : ", face.name())
1209 # Si on traite un objet solide unique, on le récupère
1210 if ( self.nom_solide_aux == self.objet_principal.name() ):
1211 if self._verbose_max:
1212 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1213 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1214 nom = "{}_Recover_2".format(self.nom_solide_aux)
1215 exec_nom (Recover_2,nom)
1217 nb_inter = face.result().numberOfSubs()
1218 if self._verbose_max:
1219 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1222 face = self._cree_face_mediane_plane_3 ( face )
1226 #=========================== Fin de la méthode ==================================
1228 #=========================== Début de la méthode =================================
1230 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, d_trans, icpt, n_recur ):
1231 """Crée la face médiane entre deux autres - cas des surfaces planes
1233 Intersection de la face avec le solide
1236 :nom_sketch: nom de l'esquisse
1237 :nom_normal: nom du vecteur normal
1238 :nom_solide: nom du solide à intersecter
1239 :d_trans: la distance de translation
1240 :icpt: numéro de la tentative
1243 :face: la face médiane
1246 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1247 blabla = "Dans {} :".format(nom_fonction)
1248 if self._verbose_max:
1249 print_tab (n_recur, blabla)
1250 print_tab (n_recur, "nom_sketch : ", nom_sketch)
1251 print_tab (n_recur, "nom_normal : ", nom_normal)
1252 print_tab (n_recur, "nom_solide : ", nom_solide)
1253 print_tab (n_recur, "d_trans : ", d_trans)
1255 # Création d'une face
1256 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1257 nom = "{}_Face_1_{}".format(self.nom_solide_aux,icpt)
1258 exec_nom (Face_1,nom)
1259 if self._verbose_max:
1260 print_tab (n_recur, "Après addFace pour Face_1 de nom ", nom)
1263 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)
1264 nom = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1265 exec_nom (Translation_1,nom)
1266 if self._verbose_max:
1267 print_tab (n_recur, "Après addTranslation pour Translation_1 de nom ", nom)
1268 Translation_1.result().setColor(85, 0, 255)
1270 # Intersection de cette face avec le solide initial
1271 face = self._creation_face_inter ( Translation_1.result().name(), nom_solide )
1275 #=========================== Fin de la méthode ==================================
1277 #=========================== Début de la méthode =================================
1279 def _cree_face_mediane_plane_3 ( self, face ):
1280 """Crée la face médiane entre deux autres - cas des surfaces planes
1282 Fusion des 2 intersections
1285 :face: la face médiane composée de plusieurs intersections
1288 :face_m: la face médiane
1291 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1292 blabla = "Dans {} :\n".format(nom_fonction)
1293 if self._verbose_max:
1297 # Nommage des sous-objets
1299 for iaux in range(face.result().numberOfSubs()):
1300 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1301 face.result().subResult(iaux).setName(nom)
1302 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1305 if self._verbose_max:
1306 print ("Fusion de {} faces.".format(len(l_fuse)))
1307 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1308 face_m.execute(True)
1312 #=========================== Fin de la méthode ==================================
1314 #=========================== Début de la méthode =================================
1316 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1317 """Crée la face médiane entre deux autres - cas des cylindres
1320 :solide: solide SHAPER à traiter
1321 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1322 :n_recur: niveau de récursivité
1325 :face: la face médiane
1328 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1329 blabla = "Dans {} :".format(nom_fonction)
1332 if self._verbose_max:
1333 print_tab (n_recur, blabla)
1334 print_tab (n_recur, "face_1 : ", caract_face_1)
1335 print_tab (n_recur, "face_2 : ", caract_face_2)
1337 # Caractéristiques des cylindres
1338 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 )
1340 # Contrôle de la validité de l'épaisseur
1341 erreur = self._verif_epaisseur ( epaisseur )
1343 # Création de la face, de couleur bleue si problème
1345 face = self._cree_face_mediane_cylindre_1 ( (coo_x, coo_y, coo_z), (axe_x, axe_y, axe_z), rayon, hauteur, n_recur )
1347 couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255, verbose=self._verbose_max)
1352 #=========================== Fin de la méthode ==================================
1354 #=========================== Début de la méthode =================================
1356 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1357 """Crée la face médiane entre deux autres - cas des cylindres
1359 Décodage des caractéristiques
1362 :solide: l'objet solide à traiter
1363 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1364 :n_recur: niveau de récursivité
1367 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1368 :axe_x, axe_y, axe_z: coordonnées de l'axe
1369 :rayon: rayon moyen entre les deux faces
1370 :hauteur: hauteur du cylindre
1371 :epaisseur: épaisseur de l'interface entre les deux faces
1374 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1375 blabla = "Dans {} :".format(nom_fonction)
1377 if self._verbose_max:
1378 print_tab (n_recur, blabla)
1379 print_tab (n_recur, "face_1 : ", caract_face_1)
1380 print_tab (n_recur, "face_2 : ", caract_face_2)
1382 # Coordonnées du centre de la base
1383 coo_x = caract_face_1[2][1]
1384 coo_y = caract_face_1[2][2]
1385 coo_z = caract_face_1[2][3]
1386 # Coordonnées de l'axe
1387 axe_x = caract_face_1[2][4]
1388 axe_y = caract_face_1[2][5]
1389 axe_z = caract_face_1[2][6]
1391 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1392 # Hauteur : une longueur caractéristique pour être certain de tout prendre
1393 l_diag = self._calcul_lg_caract ( solide, n_recur )
1394 hauteur = 10.*l_diag
1395 if self._verbose_max:
1396 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1398 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1400 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1402 #=========================== Fin de la méthode ==================================
1404 #=========================== Début de la méthode =================================
1406 def _cree_face_mediane_cylindre_1 ( self, coo_c, v_axe, rayon, hauteur, n_recur ):
1407 """Crée la face médiane entre deux autres - cas des cylindres
1409 Création des objets temporaires et de la face externe du cylindre support
1412 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1413 :axe_x, axe_y, axe_z: coordonnées de l'axe
1414 :rayon: rayon moyen entre les deux faces
1415 :hauteur: hauteur du cylindre
1416 :n_recur: niveau de récursivité
1419 :face: la face médiane
1421 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1422 blabla = "Dans {} :\n".format(nom_fonction)
1424 # Les caractéristiques du cylindre à créer
1425 if self._verbose_max:
1426 print_tab (n_recur, blabla)
1427 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1428 print_tab (n_recur, "Axe : ({}, {}, {})".format(v_axe[0], v_axe[1], v_axe[2]))
1429 print_tab (n_recur, "Rayon : ", rayon)
1430 print_tab (n_recur, "Hauteur : ", hauteur)
1432 # Création du point central
1433 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
1434 nom_centre = "{}_centre".format(self.nom_solide)
1435 exec_nom (centre,nom_centre)
1436 if self.fonction_0 is None:
1437 self.fonction_0 = centre
1439 # Création du vecteur axial
1440 axe = model.addAxis(self.part_doc, v_axe[0], v_axe[1], v_axe[2])
1441 nom_axe = "{}_vecteur".format(self.nom_solide)
1442 exec_nom (axe,nom_axe)
1444 # Création du cylindre en volume, de rayon médian
1445 Cylinder_1 = model.addCylinder(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("EDGE", nom_axe), rayon, hauteur)
1446 nom = "{}_Cylinder_1".format(self.nom_solide)
1447 exec_nom (Cylinder_1,nom)
1449 # Le groupe de la surface
1450 Group_1 = model.addGroup(self.part_doc, "Faces", [model.selection("FACE", "{}/Face_1".format(nom))])
1451 nom = "{}_Group_1".format(self.nom_solide)
1452 exec_nom (Group_1,nom)
1454 # Création du cylindre en surface
1455 cylindre = model.addGroupShape(self.part_doc, [model.selection("COMPOUND", nom)])
1456 nom = "{}_cylindre".format(self.nom_solide)
1457 exec_nom (cylindre, nom, (85, 0, 255))
1460 Translation_1 = model.addTranslation(self.part_doc, [model.selection("COMPOUND", nom)], axis = model.selection("EDGE", nom_axe), distance = -0.5*hauteur, keepSubResults = True)
1461 nom = "{}_Translation_1".format(self.nom_solide)
1462 exec_nom (Translation_1,nom)
1464 # Intersection de la face cylindrique avec le solide initial
1465 face = self._creation_face_inter ( nom )
1469 #=========================== Fin de la méthode ==================================
1471 #=========================== Début de la méthode =================================
1473 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1474 """Crée la face médiane entre deux autres - cas des sphères
1477 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1478 :n_recur: niveau de récursivité
1481 :face: la face médiane
1484 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1485 blabla = "Dans {} :".format(nom_fonction)
1488 if self._verbose_max:
1489 print_tab (n_recur, blabla)
1490 print_tab (n_recur, "face_1 : ", caract_face_1)
1491 print_tab (n_recur, "face_2 : ", caract_face_2)
1493 # Caractéristiques des sphères
1494 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1496 # Contrôle de la validité de l'épaisseur
1497 erreur = self._verif_epaisseur ( epaisseur )
1499 # Création de la face
1501 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1507 #=========================== Fin de la méthode ==================================
1509 #=========================== Début de la méthode =================================
1511 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1512 """Crée la face médiane entre deux autres - cas des sphères
1514 Décodage des caractéristiques
1517 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1518 :n_recur: niveau de récursivité
1521 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1522 :rayon: rayon moyen entre les deux faces
1523 :epaisseur: épaisseur de l'interface entre les deux faces
1526 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1527 blabla = "Dans {} :".format(nom_fonction)
1530 if self._verbose_max:
1531 print_tab (n_recur, blabla)
1532 print_tab (n_recur, "face_1 : ", caract_face_1)
1533 print_tab (n_recur, "face_2 : ", caract_face_2)
1535 # Coordonnées du centre de la sphère
1536 coo_x = caract_face_1[2][1]
1537 coo_y = caract_face_1[2][2]
1538 coo_z = caract_face_1[2][3]
1540 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1542 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1544 return coo_x, coo_y, coo_z, rayon, epaisseur
1546 #=========================== Fin de la méthode ==================================
1548 #=========================== Début de la méthode =================================
1550 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1551 """Crée la face médiane entre deux autres - cas des sphères
1553 Création des objets de construction et de la face externe de la sphère support
1556 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1557 :rayon: rayon moyen entre les deux faces
1560 :face: la face externe de la sphère support
1563 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1564 blabla = "Dans {} :\n".format(nom_fonction)
1566 # Les caractéristiques de la sphère à créer
1567 if self._verbose_max:
1569 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1570 texte += "Rayon : {}".format(rayon)
1573 # Création du point central
1574 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1575 nom_centre = "{}_centre".format(self.nom_solide)
1576 exec_nom (centre,nom_centre)
1577 if self.fonction_0 is None:
1578 self.fonction_0 = centre
1580 # Création de la sphère en volume, de rayon médian
1581 Sphere_1 = model.addSphere(self.part_doc, model.selection("VERTEX", nom_centre), rayon)
1582 nom = "{}_Sphere_1".format(self.nom_solide)
1583 exec_nom (Sphere_1,nom)
1585 # Le groupe de la surface
1586 Group_1 = model.addGroup(self.part_doc, "Faces", [model.selection("FACE", "{}/Face_1".format(nom))])
1587 nom = "{}_Group_1".format(self.nom_solide)
1588 exec_nom (Group_1,nom)
1590 # Création de la sphère en surface
1591 sphere = model.addGroupShape(self.part_doc, [model.selection("COMPOUND", nom)])
1593 nom = "{}_sphere".format(self.nom_solide)
1594 exec_nom (sphere, nom, (85, 0, 255))
1596 # Intersection de la face sphérique avec le solide initial
1597 face = self._creation_face_inter ( nom )
1601 #=========================== Fin de la méthode ==================================
1603 #=========================== Début de la méthode =================================
1605 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1606 """Crée la face médiane entre deux autres - cas des tores
1609 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1610 :n_recur: niveau de récursivité
1613 :face: la face médiane
1616 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1617 blabla = "Dans {} :".format(nom_fonction)
1620 if self._verbose_max:
1621 print_tab (n_recur, blabla)
1622 print_tab (n_recur, "face_1 : ", caract_face_1)
1623 print_tab (n_recur, "face_2 : ", caract_face_2)
1625 # Caractéristiques des tores
1626 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 )
1628 # Contrôle de la validité de l'épaisseur (bidon)
1629 erreur = self._verif_epaisseur ( EP_MIN*10. )
1631 # Création de la face
1633 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1639 #=========================== Fin de la méthode ==================================
1641 #=========================== Début de la méthode =================================
1643 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1644 """Crée la face médiane entre deux autres - cas des tores
1646 Décodage des caractéristiques
1649 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1650 :n_recur: niveau de récursivité
1653 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1654 :axe_x, axe_y, axe_z: coordonnées de l'axe
1655 :rayon_1 : rayon principal
1656 :rayon_2 : rayon secondaire
1659 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1660 blabla = "Dans {} :".format(nom_fonction)
1663 if self._verbose_max:
1664 print_tab (n_recur, blabla)
1665 print_tab (n_recur, "face_1 : ", caract_face_1)
1666 print_tab (n_recur, "face_2 : ", caract_face_2)
1668 # Coordonnées du centre du tore
1669 coo_x = caract_face_1[2][1]
1670 coo_y = caract_face_1[2][2]
1671 coo_z = caract_face_1[2][3]
1672 # Coordonnées de l'axe
1673 axe_x = caract_face_1[2][4]
1674 axe_y = caract_face_1[2][5]
1675 axe_z = caract_face_1[2][6]
1677 rayon_1 = caract_face_2[2][7]
1678 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1680 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1682 #=========================== Fin de la méthode ==================================
1684 #=========================== Début de la méthode =================================
1686 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1687 """Crée la face médiane entre deux autres - cas des tores
1689 Création des objets de construction et de la face externe du tore support
1692 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1693 :axe_x, axe_y, axe_z: coordonnées de l'axe
1694 :rayon_1 : rayon principal
1695 :rayon_2 : rayon secondaire
1698 :face: la face externe du tore support
1701 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1702 blabla = "Dans {} :\n".format(nom_fonction)
1705 if self._verbose_max:
1707 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1708 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1709 texte += "Rayon principal : {}\n".format(rayon_1)
1710 texte += "Rayon secondaire : {}".format(rayon_2)
1713 # 1. Création du point central
1714 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1715 nom_centre = "{}_centre".format(self.nom_solide)
1716 exec_nom (centre,nom_centre)
1718 # 2. Création de l'axe
1719 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1720 nom_axe = "{}_axe".format(self.nom_solide)
1721 exec_nom (axe,nom_axe)
1723 # 3. Création d'un plan passant par le centre de la base et l'axe
1724 # 3.1. Création d'un vecteur perpendiculaire à l'axe
1726 if ( (abs(axe_x)+abs(axe_y)) < self._epsilon ):
1727 v_perp = model.addAxis(self.part_doc, coeff, 0., 0.)
1729 v_perp = model.addAxis(self.part_doc, -coeff*axe_y, coeff*axe_x, 0.)
1730 nom_v_perp = "{}_v_perp".format(self.nom_solide)
1731 exec_nom (v_perp,nom_v_perp)
1732 # 3.2. Création du plan
1733 plan = model.addPlane(self.part_doc, model.selection("EDGE",nom_v_perp), model.selection("VERTEX", nom_centre), True)
1734 nom_plan = "{}_plan".format(self.nom_solide)
1735 exec_nom (plan,nom_plan)
1737 # 4. Création de l'esquisse
1738 nom_par_1 = "{}_R_1".format(self.nom_solide)
1739 param = model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1741 nom_par_2 = "{}_R_2".format(self.nom_solide)
1742 param = model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1745 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1746 sketch.execute(True)
1748 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1749 SketchProjection_1.execute(True)
1750 SketchPoint_1 = SketchProjection_1.createdFeature()
1751 SketchPoint_1.execute(True)
1753 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1754 SketchProjection_2.execute(True)
1755 SketchLine_1 = SketchProjection_2.createdFeature()
1756 SketchLine_1.execute(True)
1758 SketchPoint_2 = sketch.addPoint(rayon_1, 0.)
1759 SketchPoint_2.execute(True)
1760 contrainte = sketch.setDistance(SketchPoint_1.result(), SketchPoint_2.coordinates(), nom_par_1, True)
1761 contrainte.execute(True)
1763 SketchLine_2 = sketch.addLine(0., 0., rayon_1, 0.)
1764 SketchLine_2.execute(True)
1765 SketchLine_2.setAuxiliary(True)
1766 contrainte = sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1767 contrainte.execute(True)
1768 contrainte = sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_2.endPoint())
1769 contrainte.execute(True)
1770 contrainte = sketch.setPerpendicular(SketchLine_1.result(), SketchLine_2.result())
1771 contrainte.execute(True)
1773 SketchCircle_1 = sketch.addCircle(0., 0., rayon_2)
1774 SketchCircle_1.execute(True)
1775 contrainte = sketch.setCoincident(SketchPoint_2.result(), SketchCircle_1.center())
1776 contrainte.execute(True)
1777 contrainte = sketch.setRadius(SketchCircle_1.results()[1], nom_par_2)
1778 contrainte.execute(True)
1782 nom_sketch = "{}_esquisse".format(self.nom_solide)
1783 exec_nom (sketch,nom_sketch)
1785 # 5. Création du tore complet
1786 nom_tore = "{}_tore".format(self.nom_solide)
1787 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_tore )
1789 # 6. Intersection de la face torique avec le solide initial
1790 face = self._creation_face_inter ( nom_tore )
1794 #=========================== Fin de la méthode ==================================
1796 #=========================== Début de la méthode =================================
1798 def _cree_face_mediane_cone ( self, caract_face_1, caract_face_2, n_recur ):
1799 """Crée la face médiane entre deux autres - cas des cones
1802 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1803 :n_recur: niveau de récursivité
1806 :face: la face médiane
1809 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1810 blabla = "Dans {} :".format(nom_fonction)
1813 if self._verbose_max:
1814 print_tab (n_recur, blabla)
1815 print_tab (n_recur, "face_1 : ", caract_face_1)
1816 print_tab (n_recur, "face_2 : ", caract_face_2)
1818 # Caractéristiques des cones
1819 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 )
1821 # Contrôle de la validité de l'épaisseur (bidon)
1822 erreur = self._verif_epaisseur ( EP_MIN*10. )
1824 # Création de la face
1826 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1832 #=========================== Fin de la méthode ==================================
1834 #=========================== Début de la méthode =================================
1836 def _cree_face_mediane_cone_0 ( self, caract_face_1, caract_face_2, n_recur ):
1837 """Crée la face médiane entre deux autres - cas des cones
1839 Décodage des caractéristiques
1842 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1843 :n_recur: niveau de récursivité
1846 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1847 :axe_x, axe_y, axe_z: coordonnées de l'axe
1848 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1849 :hauteur: hauteur du cone
1852 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1853 blabla = "Dans {} :".format(nom_fonction)
1856 if self._verbose_max:
1857 print_tab (n_recur, blabla)
1858 print_tab (n_recur, "face_1 : ", caract_face_1)
1859 print_tab (n_recur, "face_2 : ", caract_face_2)
1861 # Coordonnées du centre de la base
1862 coo_x = caract_face_1[2][1]
1863 coo_y = caract_face_1[2][2]
1864 coo_z = caract_face_1[2][3]
1865 # Coordonnées de l'axe
1866 axe_x = caract_face_1[2][4]
1867 axe_y = caract_face_1[2][5]
1868 axe_z = caract_face_1[2][6]
1870 rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1871 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1873 hauteur = caract_face_1[2][9]
1876 if self._verbose_max:
1877 print_tab (n_recur, "coo_x : ", coo_x)
1878 print_tab (n_recur, "coo_y : ", coo_y)
1879 print_tab (n_recur, "coo_z : ", coo_z)
1880 print_tab (n_recur, "axe_x : ", axe_x)
1881 print_tab (n_recur, "axe_y : ", axe_y)
1882 print_tab (n_recur, "axe_z : ", axe_z)
1883 print_tab (n_recur, "rayon_1 : ", rayon_1)
1884 print_tab (n_recur, "rayon_2 : ", rayon_2)
1885 print_tab (n_recur, "hauteur : ", hauteur)
1887 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1889 #=========================== Fin de la méthode ==================================
1891 #=========================== Début de la méthode =================================
1893 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1894 """Crée la face médiane entre deux autres - cas des cones
1896 Création des objets de construction et de la face externe du cone support
1899 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1900 :axe_x, axe_y, axe_z: coordonnées de l'axe
1901 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1902 :hauteur: hauteur du cone
1905 :face: la face externe du cone support
1907 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1908 blabla = "Dans {} :\n".format(nom_fonction)
1911 if self._verbose_max:
1913 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1914 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1915 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1916 texte += "Hauteur : {}".format(hauteur)
1919 # 1. Création du point central de la base, côté rayon_1
1920 centre_1 = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1921 nom_centre_1 = "{}_centre_1".format(self.nom_solide)
1922 exec_nom (centre_1,nom_centre_1)
1924 # 2. Création du point central, du côté de rayon_2
1925 centre_2 = model.addPoint(self.part_doc, coo_x+hauteur*axe_x, coo_y+hauteur*axe_y, coo_z+hauteur*axe_z)
1926 nom_centre_2 = "{}_centre_2".format(self.nom_solide)
1927 exec_nom (centre_2,nom_centre_2)
1929 # 3. Création de l'axe
1930 axe = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("VERTEX", nom_centre_2))
1931 nom_axe = "{}_axe".format(self.nom_solide)
1932 exec_nom (axe,nom_axe)
1934 # 4. Création d'un plan passant par le centre de la base et l'axe
1935 # 4.1. Création d'un vecteur perpendiculaire à l'axe
1937 if ( (abs(axe_x)+abs(axe_y)) < self._epsilon ):
1938 v_perp = model.addAxis(self.part_doc, coeff, 0., 0.)
1940 v_perp = model.addAxis(self.part_doc, -coeff*axe_y, coeff*axe_x, 0.)
1941 nom_v_perp = "{}_v_perp".format(self.nom_solide)
1942 exec_nom (v_perp,nom_v_perp)
1943 # 4.2. Création du plan
1944 plan = model.addPlane(self.part_doc, model.selection("EDGE",nom_v_perp), model.selection("VERTEX", nom_centre_1), True)
1945 nom_plan = "{}_plan".format(self.nom_solide)
1946 exec_nom (plan,nom_plan)
1949 nom_par_1 = "{}_R_1".format(self.nom_solide)
1950 param = model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1952 nom_par_2 = "{}_R_2".format(self.nom_solide)
1953 param = model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1955 nom_par_3 = "{}_H".format(self.nom_solide)
1956 param = model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
1959 # 6. Création de l'esquisse
1961 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1962 sketch.execute(True)
1964 # 6.1. Projection des centres et de l'axe
1965 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre_1), False)
1966 SketchProjection_1.execute(True)
1967 SketchPoint_1 = SketchProjection_1.createdFeature()
1968 SketchPoint_1.execute(True)
1969 sk_coo_x_1 = SketchAPI_Point(SketchPoint_1).coordinates().x()
1970 sk_coo_y_1 = SketchAPI_Point(SketchPoint_1).coordinates().y()
1972 SketchProjection_2 = sketch.addProjection(model.selection("VERTEX", nom_centre_2), False)
1973 SketchProjection_2.execute(True)
1974 SketchPoint_2 = SketchProjection_2.createdFeature()
1975 SketchPoint_2.execute(True)
1976 sk_coo_x_2 = SketchAPI_Point(SketchPoint_2).coordinates().x()
1977 sk_coo_y_2 = SketchAPI_Point(SketchPoint_2).coordinates().y()
1979 SketchProjection_3 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1980 SketchProjection_3.execute(True)
1981 SketchLine_0 = SketchProjection_3.createdFeature()
1982 SketchLine_0.execute(True)
1984 # 6.2. Lignes perpendiculaires à l'axe passant par les centres
1985 SketchLine_1 = sketch.addLine(sk_coo_x_1, sk_coo_y_1, sk_coo_x_1+rayon_1, sk_coo_y_1)
1986 SketchLine_1.execute(True)
1987 SketchLine_1.setAuxiliary(True)
1988 contrainte = sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.startPoint())
1989 contrainte.execute(True)
1990 contrainte = sketch.setPerpendicular(SketchLine_0.result(), SketchLine_1.result())
1991 contrainte.execute(True)
1992 contrainte = sketch.setLength(SketchLine_1.result(), nom_par_1)
1993 contrainte.execute(True)
1995 SketchLine_2 = sketch.addLine(sk_coo_x_2, sk_coo_y_2, sk_coo_x_2+rayon_2, sk_coo_y_2)
1996 SketchLine_2.execute(True)
1997 SketchLine_2.setAuxiliary(True)
1998 contrainte = sketch.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_2.startPoint())
1999 contrainte.execute(True)
2000 contrainte = sketch.setPerpendicular(SketchLine_0.result(), SketchLine_2.result())
2001 contrainte.execute(True)
2002 contrainte = sketch.setLength(SketchLine_2.result(), nom_par_2)
2003 contrainte.execute(True)
2005 # 6.3. Ligne joignant les extrémités des précédentes et point milieu
2006 SketchLine_3 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
2007 SketchLine_3.execute(True)
2008 contrainte = sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_1.endPoint())
2009 contrainte.execute(True)
2010 contrainte = sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_2.endPoint())
2011 contrainte.execute(True)
2012 SketchLine_3.setAuxiliary(True)
2013 SketchPoint_3 = sketch.addPoint(sk_coo_x_1, sk_coo_y_1)
2014 SketchPoint_3.execute(True)
2015 contrainte = sketch.setMiddlePoint(SketchLine_3.result(), SketchPoint_3.coordinates())
2016 contrainte.execute(True)
2018 # 6.4. Ligne support de la future révolution
2019 SketchLine_4 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
2020 SketchLine_4.execute(True)
2021 contrainte = sketch.setMiddlePoint(SketchLine_4.result(), SketchPoint_3.coordinates())
2022 contrainte.execute(True)
2023 contrainte = sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_4.result())
2024 contrainte.execute(True)
2025 contrainte = sketch.setLength(SketchLine_4.result(), "1.2*{}".format(nom_par_3))
2026 contrainte.execute(True)
2030 nom_sketch = "{}_esquisse".format(self.nom_solide)
2031 exec_nom (sketch,nom_sketch)
2033 # 7. Création du cone complet
2034 nom_cone = "{}_cone".format(self.nom_solide)
2035 self._cree_revolution ( nom_sketch, nom_centre_1, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
2037 # 8. Intersection de la face conique avec le solide initial
2038 face = self._creation_face_inter ( nom_cone )
2042 #=========================== Fin de la méthode ==================================
2044 #=========================== Début de la méthode =================================
2046 def _cree_centre_axe_plan ( self, coo_c, vect, prefixe, n_recur ):
2047 """Crée un centre, un axe, un plan
2050 :coo_c: coordonnées du centre de la base
2051 :vect: coordonnées du vecteur
2052 :prefix: prefixe du nom des objets
2053 :n_recur: niveau de récursivité
2057 :normal: vecteur normal
2061 nom_fonction = __name__ + "/_cree_centre_axe_plan"
2062 blabla = "Dans {} :".format(nom_fonction)
2063 if self._verbose_max:
2064 print_tab (n_recur, blabla)
2065 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
2066 print_tab (n_recur, "Normale : ({}, {}, {})".format(vect[0], vect[1], vect[2]))
2068 # Création du point central
2069 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
2070 nom_centre = "{}_centre".format(prefixe)
2071 exec_nom (centre,nom_centre)
2072 if self.fonction_0 is None:
2073 self.fonction_0 = centre
2075 # Création du vecteur
2076 vecteur = model.addAxis(self.part_doc, vect[0], vect[1], vect[2])
2077 nom_vect = "{}_vecteur".format(prefixe)
2078 exec_nom (vecteur,nom_vect)
2080 # Création du plan perpendiculaire au vecteur normal
2081 plan = model.addPlane(self.part_doc, model.selection("EDGE", vecteur.name()), model.selection("VERTEX", centre.name()), True)
2082 nom_plan = "{}_plan".format(prefixe)
2083 exec_nom (plan,nom_plan)
2085 #print ("fin de {}".format(nom_fonction))
2087 return centre, vecteur, plan
2089 #=========================== Fin de la méthode ==================================
2091 #=========================== Début de la méthode =================================
2093 def _calcul_lg_caract ( self, objet, n_recur ):
2094 """Crée une longueur caractéristique de l'objet
2097 :objet: l'objet à traiter
2098 :n_recur: niveau de récursivité
2101 :l_caract: longueur caractéristique de l'objet
2104 nom_fonction = __name__ + "/_calcul_lg_caract"
2105 blabla = "Dans {} :".format(nom_fonction)
2107 if self._verbose_max:
2108 print_tab (n_recur, blabla)
2110 properties = model.getGeometryCalculation(self.part_doc,model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
2111 l_caract = properties[0]
2113 if self._verbose_max:
2114 print_tab (n_recur, "Longueur caractéristique : ", l_caract)
2118 #=========================== Fin de la méthode ==================================
2120 #=========================== Début de la méthode =================================
2122 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
2123 """Crée un volume de révolution
2126 :nom_sketch: nom de l'esquisse à révolutionner
2127 :nom_centre: nom du point associé au centre du volume de révolution
2128 :coo_x, coo_y, coo_z: coordonnées du centre du tore
2129 :axe_x, axe_y, axe_z: coordonnées de l'axe
2130 :rayon_1 : rayon principal
2131 :rayon_2 : rayon secondaire
2132 :nom_objet: nom de l'objet 2D créé
2135 nom_fonction = __name__ + "/_cree_revolution"
2136 blabla = "Dans {} :\n".format(nom_fonction)
2138 if self._verbose_max:
2140 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2141 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2144 # Création d'un point décalé par rapport au point central
2145 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
2146 nom_point = "{}_point".format(self.nom_solide)
2147 exec_nom (point,nom_point)
2149 # Création de l'axe de la rotation
2150 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
2151 nom_axe_r = "{}_axe_r".format(self.nom_solide)
2152 exec_nom (axe_r,nom_axe_r)
2154 # Création de l'objet complet
2155 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
2156 exec_nom (objet, nom_objet, (85, 0, 255))
2158 #=========================== Fin de la méthode ==================================
2160 #=========================== Début de la méthode =================================
2162 def _creation_face_inter ( self, nom_objet, nom_solide=None ):
2163 """Crée la face par intersection entre l'objet initial et une face complète
2165 . Repère la face principale de l'objet support
2166 . Réalise l'intersection avec le solide initial
2169 :nom_objet: nom de l'objet 2D créé
2170 :nom_solide: nom du solide initial ; si None, on prend self.nom_solide_aux
2173 :face: la face externe de l'objet support intersecté avec le solide initial
2176 nom_fonction = __name__ + "/_creation_face_inter"
2177 blabla = "Dans {} :\n".format(nom_fonction)
2179 if self._verbose_max:
2182 if nom_solide is None:
2183 nom_solide = self.nom_solide_aux
2185 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_objet)], keepSubResults = True)
2190 #=========================== Fin de la méthode ==================================
2192 #=========================== Début de la méthode =================================
2194 def face_mediane_solide (self, solide, n_recur=0):
2195 """Calcul de la face médiane pour un solide
2198 :solide: solide SHAPER à traiter
2199 :n_recur: niveau de récursivité
2202 :erreur: code d'erreur
2203 :message: message d'erreur
2206 nom_fonction = __name__ + "/face_mediane_solide"
2207 blabla = "Dans {} :".format(nom_fonction)
2209 if self._verbose_max:
2210 print_tab (n_recur, blabla, saut_av=True)
2212 print_tab (n_recur, "Traitement du solide ", solide.name())
2221 # 2. Calcul des caractéristiques géométriques des faces
2223 tb_caract = self._calcul_caract_faces ( solide, n_recur )
2225 # 3. Tri des faces en fonction de leurs caractéristiques géométriques
2227 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract, n_recur )
2231 # 4. Création de la face médiane
2233 erreur, face = self._cree_face_mediane ( solide, caract_face_1, caract_face_2, n_recur )
2234 if ( erreur or ( face is None ) ):
2237 # 6. Exportation step
2239 if self._export_step:
2240 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2241 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2242 export.execute(True)
2249 if ( erreur and self._verbose_max ):
2250 print (blabla, message)
2252 return erreur, message
2254 #=========================== Fin de la méthode ==================================
2256 #=========================== Début de la méthode =================================
2258 def _traitement_objet (self, solide, n_recur=0):
2259 """Traitement d'un objet
2262 :solide: solide SHAPER à traiter
2263 :n_recur: niveau de récursivité
2266 :erreur: code d'erreur
2267 :message: message d'erreur
2270 nom_fonction = __name__ + "/_traitement_objet"
2271 blabla = "Dans {} :".format(nom_fonction)
2273 if self._verbose_max:
2274 print_tab (n_recur, blabla, saut_av=True)
2275 texte = "solide = {} ".format(solide.name())
2276 print_tab (n_recur, texte, solide)
2278 # 1. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2279 # Attention à ne pas recréer le répertoire à chaque fois
2280 if self._export_step:
2282 if self.rep_step is None:
2284 if self._verbose_max:
2285 print_tab (n_recur, "Préparation de l'export STEP")
2287 if self.ficcao is None:
2288 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2290 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2291 if os.path.isdir(self.rep_step):
2292 l_aux = os.listdir(self.rep_step)
2293 for nomfic in l_aux:
2294 os.remove(os.path.join(self.rep_step,nomfic))
2296 os.mkdir(self.rep_step)
2298 if self._verbose_max:
2299 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2301 # 2. Calcul réel de la face médiane
2303 erreur, message = self.face_mediane_solide (solide, n_recur)
2305 return erreur, message
2307 #=========================== Fin de la méthode ==================================
2309 #=========================== Début de la méthode =================================
2311 def surf_fic_cao (self, ficcao, nom_objet=None):
2312 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2315 :ficcao: fichier de l'objet à traiter
2316 :nom_objet: un nom à donner à l'objet à traiter
2319 :erreur: code d'erreur
2320 :message: message d'erreur
2323 nom_fonction = __name__ + "/surf_fic_cao"
2324 blabla = "Dans {} :".format(nom_fonction)
2326 if self._verbose_max:
2336 if self.affiche_aide_globale:
2339 # 1. Définition de la pièce
2341 self.part_doc = model.activeDocument()
2342 if ( self.part_doc.kind() == "PartSet" ):
2343 part = model.addPart(self.part_doc)
2344 self.part_doc = part.document()
2346 # 2. Import de la CAO
2348 self.ficcao = ficcao
2349 print ("Traitement du fichier {}".format(ficcao))
2351 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2355 # 3. Calcul des surfaces
2357 erreur, message = self.surf_objet_shaper ( objet )
2364 if ( erreur and self._verbose_max ):
2365 print (blabla, message)
2367 return erreur, message
2369 #=========================== Fin de la méthode ==================================
2371 #=========================== Début de la méthode =================================
2373 def surf_objet_shaper (self, objet):
2374 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2377 :objet: objet à traiter
2380 :erreur: code d'erreur
2381 :message: message d'erreur
2384 nom_fonction = __name__ + "/surf_objet_shaper"
2385 blabla = "Dans {} :".format(nom_fonction)
2387 if self._verbose_max:
2395 if self.affiche_aide_globale:
2398 # 1. Acquisition de la liste des noms des sous-objets solides
2400 self.d_statut_so = dict()
2401 self.l_noms_so = list()
2402 self.l_faces_m = list()
2404 _ = self._nom_sous_objets (objet, True)
2405 if self._verbose_max:
2406 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2408 # 2. Les faces médianes
2410 erreur, message = self._surf_objet_shaper_0 ( objet )
2414 # 3. Gestion des faces créées
2416 self._surf_objet_shaper_1 ( )
2418 # 4. Futur message pour le résultat
2420 if ( self._export_step and not erreur ):
2421 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2425 return erreur, message
2427 #=========================== Fin de la méthode ==================================
2429 #=========================== Début de la méthode =================================
2431 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2432 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2435 :objet: objet à traiter
2436 :n_recur: niveau de récursivité
2439 :erreur: code d'erreur
2440 :message: message d'erreur
2443 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2444 blabla = "Dans {} :".format(nom_fonction)
2446 if self._verbose_max:
2447 print_tab (n_recur, blabla)
2448 print_tab (n_recur, "n_recur = ", n_recur)
2455 # 1. Au premier passage, il faut récupérer la pièce SHAPER et garder la référence au résultat principal
2457 if ( n_recur == 0 ):
2458 self.part_doc = model.activeDocument()
2459 objet_0 = objet.result()
2460 self.objet_principal = objet_0
2461 objet_bis = objet.defaultResult().shape()
2462 if self._verbose_max:
2463 print_tab (0, "Examen de l'objet initial ", objet.result().name(), saut_av=True)
2464 print_tab (0, "Type python : ", type(objet))
2465 print_tab (0, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2468 if self._verbose_max:
2469 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2470 print_tab (n_recur, "Type python : ", type(objet))
2471 print_tab (n_recur, "shapeType : ", objet.shapeType())
2473 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2475 nb_sub_results = objet_0.numberOfSubs()
2477 if self._verbose_max:
2478 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType(), saut_av=True)
2479 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2481 for n_sobj in range(nb_sub_results):
2483 # 2.1. Exploration récursive de l'arborescence
2485 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2492 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2494 if ( objet_0.shapeType() == "SOLID" ):
2495 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2499 # 3. Futur message pour le résultat
2501 if self._export_step:
2502 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2506 return erreur, message
2508 #=========================== Fin de la méthode ==================================
2510 #=========================== Début de la méthode =================================
2512 def _surf_objet_shaper_1 (self, n_recur=0):
2513 """Gestion des surfaces médianes créées
2516 :n_recur: niveau de récursivité
2519 :erreur: code d'erreur
2520 :message: message d'erreur
2523 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2524 blabla = "Dans {} :\n".format(nom_fonction)
2526 if self._verbose_max:
2527 print_tab (n_recur, blabla)
2529 # 1. Informations sur les faces à problème
2531 if self.faces_pb_nb:
2532 if ( self.faces_pb_nb == 1 ):
2533 texte = "1 face pose"
2535 texte = "{} faces posent".format(self.faces_pb_nb)
2536 print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2538 # 2. Si plus d'une face a été créée
2539 if ( len(self.l_faces_m) > 1 ):
2541 # 2.1. Partition du paquet de faces
2543 if self._verbose_max:
2544 print_tab (n_recur, "Partitionnnement des faces créées.")
2546 # 2.1.1. Pour une raison mystérieuse, il faut commencer par les faces entières, puis mettre les sous-faces éventuelles
2548 for (face,_) in self.l_faces_m:
2549 if not face.result().numberOfSubs():
2550 d_faces[face.name()] = [face.name()]
2551 for (face,_) in self.l_faces_m:
2552 nb_sub_results = face.result().numberOfSubs()
2555 for n_sobj in range(nb_sub_results):
2556 laux.append(face.result().subResult(n_sobj).name())
2557 d_faces[face.name()] = laux
2560 for _, laux in d_faces.items():
2561 for s_face_n in laux:
2562 l_objets.append(model.selection("FACE", s_face_n))
2564 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2565 nom = "{}_M".format(self.objet_principal.name())
2566 exec_nom (Partition_1,nom)
2569 for face_n, laux in d_faces.items():
2570 Partition_1.result().subResult(iaux).setName("{}".format(face_n))
2571 if ( len(laux) > 1 ):
2572 for jaux, s_face_n in enumerate(laux):
2573 Partition_1.result().subResult(iaux).subResult(jaux).setName("{}_M".format(s_face_n))
2575 couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0, verbose=self._verbose_max)
2577 # 2.2. Récupération des faces individuelles
2579 if self._verbose_max:
2580 print_tab (n_recur, "Récupération des faces individuelles.")
2583 for iaux, (face,_) in enumerate(self.l_faces_m):
2584 l_objets.append(face.result())
2586 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2587 exec_nom (Recover_1)
2588 for iaux, (face,_) in enumerate(self.l_faces_m):
2589 Recover_1.results()[iaux].setName("{}".format(face.name()))
2590 Recover_1.results()[iaux].setColor(0, 170, 0)
2591 nb_sub_results = Recover_1.results()[iaux].numberOfSubs()
2592 for n_sobj in range(nb_sub_results):
2593 Recover_1.results()[iaux].subResult(n_sobj).setName("{}_{}".format(face.name(),n_sobj))
2594 Recover_1.results()[iaux].subResult(n_sobj).setColor(0, 170, 0)
2596 # 3. Mise en dossier
2598 if self._verbose_max:
2599 print_tab (n_recur, "Mise en dossier.")
2601 for (face,fonction_0) in self.l_faces_m:
2602 if fonction_0 is not None:
2603 nom = face.name()[:-2]
2604 if self._verbose_max:
2605 print ( "Dossier {} de {} à {}".format(nom,fonction_0.name(),face.name()))
2606 dossier = model.addFolder(self.part_doc, fonction_0, face)
2607 dossier.setName(nom)
2609 if ( len(self.l_faces_m) > 1 ):
2611 nom = self.objet_principal.name()
2612 if self._verbose_max:
2613 print ( "Dossier {} de {} à {}".format(nom,Partition_1.name(),Recover_1.name()))
2614 dossier = model.addFolder(self.part_doc, Partition_1, Recover_1)
2615 dossier.setName(nom)
2617 #=========================== Fin de la méthode ==================================
2619 #=========================== Début de la méthode =================================
2621 def surf_solide_shaper (self, solide, n_recur):
2622 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2625 :solide: solide SHAPER à traiter
2626 :n_recur: numéro de la récurrence
2629 :erreur: code d'erreur
2630 :message: message d'erreur
2633 nom_fonction = __name__ + "/surf_solide_shaper"
2634 blabla = "Dans {} :".format(nom_fonction)
2636 if self._verbose_max:
2637 print_tab (n_recur, blabla, saut_av=True)
2644 self.nom_solide = solide.name()
2645 if self._verbose_max:
2646 print_tab (n_recur, "solide : ", self.nom_solide)
2648 # 1. Isolement du solide
2649 solide_aux, recover = self._isole_solide ( solide, n_recur )
2651 # 2. Traitement de l'objet correspondant
2652 erreur, message = self._traitement_objet ( solide_aux, n_recur=n_recur )
2654 if ( erreur and self._verbose_max ):
2655 print (blabla, message)
2657 # 3. Neutralisation des erreurs dues à l'épaisseur
2658 if ( erreur in (-2,-1,2) ):
2664 # 4. Mise en forme de l'objet principal récupéré
2665 if ( recover is not None ):
2666 _ = self._nom_sous_objets (recover, False)
2670 return erreur, message
2672 #=========================== Fin de la méthode ==================================
2674 #========================== Fin de la classe ====================================