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__ = "V10.52"
41 #========================= Les imports - Début ===================================
53 from SketchAPI import *
54 from salome.shaper import model
56 from GeomAlgoAPI import *
58 from salome.geom import geomBuilder
62 #========================== Les imports - Fin ====================================
65 D_FMT["stp"] = ["stp", "step"]
66 D_FMT["igs"] = ["igs", "iges"]
67 for CLE in ("brep", "xao"):
70 # statut = 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
89 # Transparence des solides traités correctement
92 # Limite basse de l'épaisseur pour pouvoir faire les intersections
95 #========================= Début de la fonction ==================================
97 def decode_cao (fmt_cao):
98 """Décode le format de la cao
101 :fmt_cao: format du fichier, step, iges, etc.
103 :fmt_cao_0: format décodé
108 fmt_cao_low = fmt_cao.lower()
110 for cle, l_aux in D_FMT.items():
111 if ( fmt_cao_low in l_aux ):
117 #========================= Fin de la fonction ===================================
119 #========================= Début de la fonction ==================================
121 def import_cao (part_doc, ficcao, nom_objet=None, verbose=False):
122 """Importation d'une cao
126 :ficcao: le fichier de la CAO
127 :nom_objet: nom à donner à l'objet lu, éventuellement
129 :objet: l'objet importé dans SHAPER
132 nom_fonction = __name__ + "/import_cao"
133 blabla = "\nDans {} :\n".format(nom_fonction)
134 message_0 = "Fichier : {}\n".format(ficcao)
136 message = blabla + message_0
137 message += "nom_objet : {}".format(nom_objet)
145 laux = ficcao.split(".")
146 fmt_cao_0 = decode_cao (laux[-1])
148 if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
149 message += "Le format de CAO est inconnu"
153 message += "Le fichier de CAO n'a pas été décodé correctement."
156 elif not os.path.isfile(ficcao):
157 message += "Le fichier de CAO est inconnu."
163 objet = model.addImport(part_doc, ficcao)
167 if nom_objet is not None:
168 objet.result().setName(nom_objet)
171 texte = "Objet : '{}'\n".format(objet.result().name())
172 texte += "De type : '{}'".format(objet.result().shapeType())
175 return erreur, message, objet
177 #========================= Fin de la fonction ===================================
179 #========================= Début de la fonction ==================================
181 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
182 """Imprime avec des tabulations
185 :nb_tab: nombre de tabulations à appliquer
186 :message: message principal
187 :argu: argument du format
188 :saut_av: saut de ligne avant le texte
189 :saut_ap: saut de ligne après le texte
197 for _ in range(nb_tab):
201 if ( argu is not None ):
202 texte += "{}".format(argu)
208 #========================= Fin de la fonction ===================================
211 #=================================== La classe ===================================
213 class SurfaceMediane (object):
215 """Calcul des surfaces médianes de solides minces
217 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
218 une structure qui est un solide ou un assemblage de solides (compound).
219 Pour réaliser l'opération, trois façons de faire :
221 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
223 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
224 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
226 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
227 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
230 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
231 de taille identique et supérieure aux tailles des autres faces du solide. \
232 Cela fonctionne pour des surfaces planes ou de forme canonique.
233 Il crée alors une surface au milieu de ces deux grandes faces. \
234 Cette face est coloriée en vert, le solide est en vert et transparent.
236 On sait traiter les faces :
243 Si la création n'a pas eu lieu, un message est émis et les solides sont mise en couleur :
244 . Rouge : le solide n'est pas assez mince.
245 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
246 . Orange : la forme de la face n'est pas reconnue.
254 . Exportation finale dans un fichier step. Par défaut, pas d'export.
255 -export_step/-no_export_step
258 surf_fic_cao --> import_cao
259 --> surf_objet_shaper (récursif) --> _nom_sous_objets
260 --> _surf_objet_shaper_0
261 --> surf_solide_shaper --> _isole_solide
262 --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
264 --> _cree_face_mediane
266 _cree_face_mediane --> _cree_face_mediane_plane
267 --> _cree_face_mediane_cylindre
268 --> _cree_face_mediane_sphere
269 --> _cree_face_mediane_tore
270 --> _cree_face_mediane_cone
271 --> _cree_face_mediane_0
280 affiche_aide_globale = 0
287 nom_solide_aux = None
293 objet_principal = None
295 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
297 # Statut de chaque sous-objet connu par son nom :
298 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
300 # Liste des faces médianes créées et des fonctions initiales
302 # La fonction initiale
308 #=========================== Début de la méthode =================================
310 def __init__ ( self, liste_option ):
312 """Le constructeur de la classe SurfaceMediane
314 Décodage des arguments
315 On cherche ici les arguments généraux : aide, verbeux
318 for option in liste_option :
321 if isinstance(option,str):
322 saux = option.upper()
324 if saux in ( "-H", "-HELP" ):
325 self.affiche_aide_globale = 1
328 elif saux == "-VMAX" :
330 self._verbose_max = 1
331 elif saux == "-EXPORT_STEP":
332 self._export_step = True
333 elif saux == "-NO_EXPORT_STEP":
334 self._export_step = False
336 #=========================== Fin de la méthode ==================================
338 #=========================== Début de la méthode =================================
341 """A la suppression de l'instance de classe"""
342 if self._verbose_max:
343 print ("Suppression de l'instance de la classe.")
345 #=========================== Fin de la méthode ==================================
347 #=========================== Début de la méthode =================================
349 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
350 """Gère les noms des sous_objets solides
353 :objet: objet à traiter
354 :lecture: vrai pour lire les noms, faux pour les attribuer
355 :n_recur: niveau de récursivité
356 :rang: rang du sous-objet
359 :rang: rang du sous-objet
362 nom_fonction = __name__ + "/_nom_sous_objets"
363 blabla = "Dans {} :\n".format(nom_fonction)
365 if self._verbose_max:
367 for _ in range(n_recur):
369 texte = "\n{}{}".format(prefixe,blabla)
370 texte += "{}n_recur = {}".format(prefixe,n_recur)
371 texte += "\n{}lecture = {}".format(prefixe,lecture)
374 # 1. Au premier passage, il faut garder la référence au résultat principal
377 objet_0 = objet.result()
378 if self._verbose_max:
379 print ("d_statut_so = {}".format(self.d_statut_so))
383 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
385 nb_sub_results = objet_0.numberOfSubs()
387 if self._verbose_max:
388 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
389 texte += "de type '{}'".format(objet_0.shapeType())
390 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
393 for n_sobj in range(nb_sub_results):
395 # 2.1. Exploration récursive de l'arborescence
397 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
399 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
401 if ( objet_0.shapeType() == "SOLID" ):
402 # A la lecture, on enregistre le nom
405 self.l_noms_so.append(nom)
406 self.d_statut_so[nom] = 0
407 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
409 nom = self.l_noms_so[rang]
411 etat = self.d_statut_so[nom]
412 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
414 objet_0.setTransparency (TRANSPARENCE)
419 #=========================== Fin de la méthode ==================================
421 #=========================== Début de la méthode =================================
423 def _couleur_objet (self, objet, n_recur=0, coul_r=1, coul_g=0, coul_b=0):
424 """Appliquer une couleur à un objet et à ses sous_objets
427 :objet: objet à traiter
428 :n_recur: niveau de récursivité
429 :coul_r,coul_g,coul_b: code RGB de la couleur à appliquer
432 :rang: rang du sous-objet
435 nom_fonction = __name__ + "/_couleur_objet"
436 blabla = "Dans {} :\n".format(nom_fonction)
438 if self._verbose_max:
440 for _ in range(n_recur):
442 texte = "\n{}{}".format(prefixe,blabla)
443 texte += "{}n_recur = {}".format(prefixe,n_recur)
444 texte += "\n{}RGB = ({},{},{})".format(prefixe,coul_r,coul_g,coul_b)
447 # 1. Au premier passage, il faut garder la référence au résultat principal
450 objet_0 = objet.result()
454 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
456 nb_sub_results = objet_0.numberOfSubs()
458 if self._verbose_max:
459 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
460 texte += "de type '{}' ".format(objet_0.shapeType())
461 texte += "et de {} sous-objets".format(nb_sub_results)
464 for n_sobj in range(nb_sub_results):
466 # 2.1. Exploration récursive de l'arborescence
468 self._couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b )
470 # 2.2. Cet objet n'a pas de sous-objets : on le colore
471 if self._verbose_max:
472 texte = "{}Couleur affectée à l'objet '{}' ".format(prefixe,objet_0.name())
474 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
476 #print ("sortie de {}".format(nom_fonction))
480 #=========================== Fin de la méthode ==================================
482 #=========================== Début de la méthode =================================
484 def _isole_solide ( self, solide, n_recur ):
485 """Isole le solide de son arboresence
488 :solide: le solide à traiter
489 :n_recur: numéro de la récurrence
492 :objet: le solide isolé
493 :recover: la fonction de récupération
496 nom_fonction = __name__ + "/_isole_solide"
497 blabla = "\nDans {} :".format(nom_fonction)
498 if self._verbose_max:
500 texte = "Pour le solide '{}' ".format(solide.name())
501 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
502 print_tab (n_recur, texte)
504 if ( solide.name() != self.objet_principal.name() ):
506 if self._verbose_max:
507 print_tab (n_recur, ". Extraction du solide")
509 # 1. Extraction du solide
510 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
511 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
513 self.nom_solide_aux = "{}_S".format(solide.name())
514 remove_subshapes.result().setName(self.nom_solide_aux)
516 self.fonction_0 = remove_subshapes
518 # 2. Récupération de l'objet principal
519 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
520 recover.result().setName(self.objet_principal.name())
522 objet = remove_subshapes.result()
526 if self._verbose_max:
527 print_tab (n_recur, ". Mise en place du solide")
530 self.nom_solide_aux = self.objet_principal.name()
531 self.fonction_0 = None
534 if self._verbose_max:
535 print_tab (n_recur, "objet final : ", objet.name())
536 print_tab (n_recur, "fonction_0 : ", self.fonction_0)
537 print_tab (n_recur, "recover : ", recover)
539 return objet, recover
541 #=========================== Fin de la méthode ==================================
543 #=========================== Début de la méthode =================================
545 def _faces_du_solide ( self, geompy, objet_geom, solide, n_recur=0 ):
546 """Détermine les faces d'un solide
549 :geompy: environnement de GEOM
550 :objet_geom: l'objet solide à traiter au format GEOM
551 :solide: solide SHAPER à traiter
552 :n_recur: niveau de récursivité
555 :l_faces_geom: liste des faces du solide au format GEOM
556 :l_faces: liste des faces du solide
559 nom_fonction = __name__ + "/_faces_du_solide"
560 blabla = "\nDans {} :\n".format(nom_fonction)
561 if self._verbose_max:
566 l_faces_geom = list()
569 while ( not erreur ):
571 if self._verbose_max:
572 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
573 longueur, aire, volume = geompy.BasicProperties(objet_geom)
574 texte = "{}".format(geompy.WhatIs(objet_geom))
575 texte += ". longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
578 # Liste des faces qui composent le solide
579 l_faces_geom = geompy.ExtractShapes(objet_geom, geompy.ShapeType["FACE"], True)
580 #if self._verbose_max:
581 #print ("Liste des {} faces qui composent le solide :".format(len(l_faces_geom)))
582 #for iaux, face in enumerate(l_faces_geom):
583 #print ("Face n° {} :\n {}".format(iaux,geompy.WhatIs(face)))
585 print_tab (n_recur, "Type python : ", type(solide))
586 print_tab (n_recur, "Type ", solide.shapeType())
587 #print ("Type {}".format(solide.shapeTypeStr()))
588 #print ("volume = {}".format(GeomAlgoAPI_ShapeTools.volume(solide)))
590 #exp = GeomAPI_ShapeExplorer(solide, GeomAPI_Shape.FACE)
592 #l_faces.append(exp.current().face())
597 return erreur, message, l_faces_geom, l_faces
599 #=========================== Fin de la méthode ==================================
601 #=========================== Début de la méthode =================================
603 def _calcul_caract_faces ( self, geompy, l_faces ):
604 """Calcule les caractéristiques géométriques des faces
607 :geompy: environnement de GEOM
608 :l_faces: liste des faces du solide
611 :tb_caract: tableau des caractéristiques géométriques des faces
614 nom_fonction = __name__ + "/_calcul_caract_faces"
615 blabla = "\nDans {} :\n".format(nom_fonction)
617 nb_faces = len(l_faces)
618 if self._verbose_max:
619 print (blabla+"Nombre de faces : {}.".format(nb_faces))
621 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
622 for iaux, face in enumerate(l_faces):
623 _, aire, _ = geompy.BasicProperties(face)
624 #longueur, aire, volume = geompy.BasicProperties(face)
625 if self._verbose_max or True:
626 texte = "\t. Face numéro {}".format(iaux)
627 #texte += "\n\t. longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
628 texte += ", surface : {}".format(aire)
631 tb_caract [iaux][0] = face
632 tb_caract [iaux][1] = aire
633 tb_caract [iaux][2] = geompy.KindOfShape(face)
634 if self._verbose_max:
635 print ("\t. tb_caract : {} {}".format(aire,tb_caract[iaux][2]))
639 #=========================== Fin de la méthode ==================================
641 #=========================== Début de la méthode =================================
643 def _tri_faces ( self, tb_caract ):
644 """Trie les faces en fonction de leurs surfaces
647 :tb_caract: tableau des caractéristiques géométriques des faces
650 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
656 nom_fonction = __name__ + "/_tri_faces"
657 blabla = "\nDans {} :\n".format(nom_fonction)
659 # Tri du tableau en fonction des surfaces
660 if self._verbose_max:
661 print (blabla+"tb_caract brut : {}".format(tb_caract))
662 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
663 if self._verbose_max:
664 print ("tb_caract trié : {}".format(tb_caract_1))
666 if self._verbose_max:
667 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
668 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
669 if self._verbose_max:
670 texte += "\n\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
673 # La surface suivante doit être différente, sinon ce n'est pas un solide mince
674 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
675 if ( ecart < self._epsilon ):
676 message = "\nSolide '{}'\n".format(self.nom_solide)
677 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
678 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
679 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
680 if self._verbose_max:
681 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
682 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
683 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
685 self.d_statut_so[self.nom_solide] = -1
686 self.faces_pb_nb += 1
687 self.faces_pb_msg += message
689 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
691 #=========================== Fin de la méthode ==================================
693 #=========================== Début de la méthode =================================
695 def _calcul_caract_aretes_face ( self, geompy, caract_face ):
696 """Détermine les caractéristiques des arêtes d'une face
699 :geompy: environnement de GEOM
700 :caract_face: les caractéristiques de la face
703 :caract_arete_face: les caractéristiques des arêtes de la face
706 nom_fonction = __name__ + "/_calcul_caract_aretes_face"
707 blabla = "\nDans {} :\n".format(nom_fonction)
709 if self._verbose_max:
711 texte += "face : {}\n".format(caract_face)
714 # Détermination des arêtes pour chaque face
715 face = caract_face[0]
716 l_aretes = geompy.ExtractShapes(face, geompy.ShapeType["EDGE"], True)
717 caract_arete_face = list()
718 for arete in l_aretes:
719 caract_arete_face.append(geompy.KindOfShape(arete))
721 if self._verbose_max:
722 print ("Aretes de la face : {}".format(caract_arete_face))
724 return caract_arete_face
726 #=========================== Fin de la méthode ==================================
728 #=========================== Début de la méthode =================================
730 def _verif_epaisseur ( self, epaisseur ):
731 """Contrôle de la validité de l'épaisseur
734 :epaisseur: épaisseur du solide
737 nom_fonction = __name__ + "/_verif_epaisseur"
738 blabla = "\nDans {} :\n".format(nom_fonction)
740 if self._verbose_max:
742 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
743 texte += ". EP_MIN : {}".format(EP_MIN)
746 if ( epaisseur <= EP_MIN ):
747 message = "\nSolide '{}'\n".format(self.nom_solide)
748 message += ". Epaisseur : {}\n".format(epaisseur)
749 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
750 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
752 self.d_statut_so[self.nom_solide] = 2
753 self.faces_pb_nb += 1
754 self.faces_pb_msg += message
761 #=========================== Fin de la méthode ==================================
763 #=========================== Début de la méthode =================================
765 def _cree_face_mediane ( self, solide, geompy, caract_face_1, caract_face_2, n_recur ):
766 """Crée la face médiane entre deux autres
769 :solide: solide SHAPER à traiter
770 :geompy: environnement de GEOM
771 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
772 :n_recur: niveau de récursivité
775 :face: la face médiane créée
778 nom_fonction = __name__ + "/_cree_face_mediane"
779 blabla = "\nDans {} :\n".format(nom_fonction)
781 if self._verbose_max:
783 print_tab (n_recur, "face_1 : " ,caract_face_1)
784 print_tab (n_recur, "face_2 : " ,caract_face_2)
789 # 1. Forme de la face
790 forme = caract_face_1[2][0]
791 if self._verbose_max:
792 print ("forme = {}".format(forme) )
794 # 2. Traitement selon la forme de la face
796 if forme in ( geompy.kind.DISK_CIRCLE, geompy.kind.DISK_ELLIPSE, geompy.kind.POLYGON, geompy.kind.PLANE, geompy.kind.PLANAR):
797 erreur, face = self._cree_face_mediane_plane ( geompy, solide, caract_face_1, caract_face_2, n_recur )
799 # 2.2. Face cylindrique
800 elif forme == geompy.kind.CYLINDER2D:
801 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
803 # 2.3. Face sphérique
804 elif forme == geompy.kind.SPHERE2D:
805 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
808 elif forme == geompy.kind.TORUS2D:
809 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
812 elif forme == geompy.kind.CONE2D:
813 erreur, face = self._cree_face_mediane_cone ( geompy, caract_face_1, caract_face_2, n_recur )
815 # 2.N. Face de forme inconnue
817 message = "\nSolide '{}'\n".format(self.nom_solide)
818 message += "sa face la plus grande est de forme : {}\n".format(forme)
819 message += "==> Impossible de créer la face médiane.\n"
821 self.d_statut_so[self.nom_solide] = -2
822 self.faces_pb_nb += 1
823 self.faces_pb_msg += message
825 # 3. Gestion de la face produite
828 self._cree_face_mediane_0 ( face, n_recur )
832 #=========================== Fin de la méthode ==================================
834 #=========================== Début de la méthode =================================
836 def _cree_face_mediane_0 ( self, face, n_recur ):
837 """Gestion de la face médiane créée entre deux autres
840 :face: la face médiane créée
841 :n_recur: niveau de récursivité
844 nom_fonction = __name__ + "/_cree_face_mediane_0"
845 blabla = "\nDans {} :\n".format(nom_fonction)
847 if self._verbose_max:
851 nom_face = self.nom_solide+"_M"
852 #if ( self.nom_solide_aux != self.objet_principal.name() ):
854 face.setName(nom_face)
855 face.result().setName(nom_face)
857 # 2. Mémorisation de la face et de la fonction initiale
858 self.l_faces_m.append((face, self.fonction_0))
860 # 3. Couleur verte pour la face
861 self._couleur_objet (face, coul_r=0, coul_g=170, coul_b=0)
863 # 4. Changement de statut pour le solide
864 self.d_statut_so[self.nom_solide] = 1
868 #=========================== Fin de la méthode ==================================
870 #=========================== Début de la méthode =================================
872 def _cree_face_mediane_plane ( self, geompy, solide, caract_face_1, caract_face_2, n_recur ):
873 """Crée la face médiane entre deux autres - cas des surfaces planes
876 :geompy: environnement de GEOM
877 :solide: l'objet solide à traiter
878 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
879 :n_recur: niveau de récursivité
882 :face: la face médiane
885 nom_fonction = __name__ + "/_cree_face_mediane_plane"
886 blabla = "\nDans {} :\n".format(nom_fonction)
887 if self._verbose_max:
890 # Caractéristiques des surfaces
891 coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2 = self._cree_face_mediane_plane_0 ( geompy, solide, caract_face_1, caract_face_2, n_recur )
893 # Contrôle de la validité de l'épaisseur
894 erreur = self._verif_epaisseur ( d_face_1_2 )
896 # Création de la face
898 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 )
904 #=========================== Fin de la méthode ==================================
906 #=========================== Début de la méthode =================================
908 def _cree_face_mediane_plane_0 ( self, geompy, solide, caract_face_1, caract_face_2, n_recur ):
909 """Crée la face médiane entre deux autres - cas des surfaces planes
911 Décodage des caractéristiques
914 :geompy: environnement de GEOM
915 :solide: l'objet solide à traiter
916 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
917 :n_recur: niveau de récursivité
920 :coo_x, coo_y, coo_z: coordonnées du centre de la base
921 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
922 :taille: estimation de la taille de la future face
923 :d_face_1_2: la distance entre les deux faces
926 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
927 blabla = "\nDans {} :".format(nom_fonction)
929 if self._verbose_max:
931 print_tab (n_recur, "face_1 : ", caract_face_1)
932 print_tab (n_recur, "face_2 : ", caract_face_2)
934 # 1. Caractéristiques de la base
935 # Coordonnées du centre de la base
936 coo_x = caract_face_1[2][1]
937 coo_y = caract_face_1[2][2]
938 coo_z = caract_face_1[2][3]
939 # Coordonnées du vecteur normal
940 vnor_x = caract_face_1[2][4]
941 vnor_y = caract_face_1[2][5]
942 vnor_z = caract_face_1[2][6]
943 # taille : la diagonale de la boîte englobante permet d'être certain de tout prendre
944 l_diag = self._calcul_boite_englobante ( solide, n_recur )
946 if self._verbose_max:
947 print_tab (n_recur, "Taille englobante : ",taille)
949 # 2. Distance entre les deux faces
950 face_1 = caract_face_1[0]
951 face_2 = caract_face_2[0]
952 d_face_1_2 = geompy.MinDistance(face_1, face_2)
953 if self._verbose_max:
954 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
956 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
958 #=========================== Fin de la méthode ==================================
960 #=========================== Début de la méthode =================================
962 def _cree_face_mediane_plane_1 ( self, solide, coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2, n_recur ):
963 """Crée la face médiane entre deux autres - cas des surfaces planes
965 Création des objets temporaires et de la face médiane
968 :solide: l'objet solide à traiter
969 :coo_x, coo_y, coo_z: coordonnées du centre de la base
970 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
971 :taille: estimation de la taille de la future face
972 :d_face_1_2: la distance entre les deux faces
975 :face: la face médiane
978 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
979 blabla = "\nDans {} :".format(nom_fonction)
980 if self._verbose_max:
982 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_x, coo_y, coo_z))
983 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor_x, vnor_y, vnor_z))
984 print_tab (n_recur, "Taille : ", taille)
985 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
987 # Création de paramètres
988 nom_par_1 = "{}_taille".format(self.nom_solide)
989 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(taille))
991 # Création du point central
992 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
993 nom_centre = "{}_centre".format(self.nom_solide)
994 centre.result().setName(nom_centre)
996 # Création du vecteur normal
997 v_norm = model.addAxis(self.part_doc, vnor_x, vnor_y, vnor_z)
998 nom_normal = "{}_normale".format(self.nom_solide)
999 v_norm.result().setName(nom_normal)
1001 # Création du plan perpendiculaire au vecteur normal
1002 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_normal), model.selection("VERTEX", nom_centre), True)
1003 nom_plan = "{}_plan".format(self.nom_solide)
1004 plan.result().setName(nom_plan)
1006 # Création d'un sketch
1007 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1009 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1010 SketchPoint_1 = SketchProjection_1.createdFeature()
1012 ### Create SketchLine
1013 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1015 ### Create SketchLine
1016 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1018 ### Create SketchLine
1019 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1021 ### Create SketchLine
1022 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1023 sketch.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
1024 sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
1025 sketch.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
1026 sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
1028 ### Create SketchLine
1029 SketchLine_5 = sketch.addLine(-taille/2., taille/2., taille/2., -taille/2.)
1030 SketchLine_5.setAuxiliary(True)
1032 ### Create SketchLine
1033 SketchLine_6 = sketch.addLine(taille/2., taille/2., -taille/2., -taille/2.)
1034 SketchLine_6.setAuxiliary(True)
1035 sketch.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
1036 sketch.setCoincident(SketchLine_2.startPoint(), SketchLine_6.startPoint())
1037 sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_5.endPoint())
1038 sketch.setCoincident(SketchLine_4.startPoint(), SketchLine_6.endPoint())
1039 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_5.result())
1040 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_6.result())
1041 sketch.setHorizontal(SketchLine_1.result())
1042 sketch.setVertical(SketchLine_2.result())
1043 sketch.setHorizontal(SketchLine_3.result())
1044 sketch.setVertical(SketchLine_4.result())
1045 sketch.setLength(SketchLine_3.result(), nom_par_1)
1046 sketch.setEqual(SketchLine_3.result(), SketchLine_4.result())
1049 nom_sketch = "{}_esquisse".format(self.nom_solide)
1050 sketch.setName(nom_sketch)
1051 sketch.result().setName(nom_sketch)
1053 ### Create LinearCopy
1054 LinearCopy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1055 LinearCopy_1.result().subResult(0).setName("{}_0".format(self.nom_solide_aux))
1058 Recover_1 = model.addRecover(self.part_doc, LinearCopy_1, [solide])
1059 Recover_1.result().setName("{}_1".format(self.nom_solide_aux))
1061 # Création d'une face ; on la translate d'une demi-épaisseur.
1062 for iaux in range(2):
1064 distance = -0.5*d_face_1_2*float(2*iaux-1)
1065 nom_solide = "{}_{}".format(self.nom_solide_aux,iaux)
1066 face = self._cree_face_mediane_plane_2 ( nom_sketch, nom_normal, nom_solide, distance, iaux )
1069 # Si on traite un objet solide unique, on le récupère
1070 if ( self.nom_solide_aux == self.objet_principal.name() ):
1071 if self._verbose_max:
1072 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1073 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1074 Recover_2.result().setName("{}_S".format(self.nom_solide_aux))
1075 nb_inter = face.result().numberOfSubs()
1076 if self._verbose_max:
1077 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1078 # Une seule intersection : c'est la bonne
1079 # Sinon, c'est que le solide est trop mince. On fusionnerait les faces.
1081 face = self._cree_face_mediane_plane_3 ( face )
1083 # Si l'intersection est vide, on la translate dans l'autre sens
1085 if self._verbose_max:
1086 print_tab (n_recur, "L'intersection est vide.")
1091 #=========================== Fin de la méthode ==================================
1093 #=========================== Début de la méthode =================================
1095 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, distance, icpt=0 ):
1096 """Crée la face médiane entre deux autres - cas des surfaces planes
1098 Intersection de la face avec le solide
1101 :nom_sketch: nom du sketch
1102 :nom_normal: nom du vecteur normal
1103 :nom_solide: nom du solide à intersecter
1104 :distance: la distance de translation
1105 :icpt: numéro de la tentative
1108 :face: la face médiane
1111 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1112 blabla = "\nDans {} :\n".format(nom_fonction)
1113 if self._verbose_max:
1115 texte += "nom_sketch : {}\n".format(nom_sketch)
1116 texte += "nom_normal : {}\n".format(nom_normal)
1117 texte += "nom_solide : {}\n".format(nom_solide)
1118 texte += "distance : {}".format(distance)
1121 # Création d'une face
1122 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1123 nom_face_1 = "{}_face_1_{}".format(self.nom_solide_aux,icpt)
1124 Face_1.result().setName(nom_face_1)
1127 Translation_1 = model.addTranslation(self.part_doc, [model.selection("FACE", nom_face_1)], axis = model.selection("EDGE", nom_normal), distance = distance, keepSubResults = True)
1128 nom_trans = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1129 Translation_1.setName(nom_trans)
1130 Translation_1.result().setName(nom_trans)
1131 Translation_1.result().setColor(85, 0, 255)
1133 # Intersection de cette face avec le solide initial
1134 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_trans)], keepSubResults = True)
1138 #=========================== Fin de la méthode ==================================
1140 #=========================== Début de la méthode =================================
1142 def _cree_face_mediane_plane_3 ( self, face ):
1143 """Crée la face médiane entre deux autres - cas des surfaces planes
1145 Fusion des 2 intersections
1148 :face: la face médiane composée de plusieurs intersections
1151 :face_m: la face médiane
1154 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1155 blabla = "\nDans {} :\n".format(nom_fonction)
1156 if self._verbose_max:
1160 # Nommage des sous-objets
1162 for iaux in range(face.result().numberOfSubs()):
1163 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1164 face.result().subResult(iaux).setName(nom)
1165 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1168 if self._verbose_max:
1169 print ("Fusion de {} faces.".format(len(l_fuse)))
1170 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1174 #=========================== Fin de la méthode ==================================
1176 #=========================== Début de la méthode =================================
1178 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1179 """Crée la face médiane entre deux autres - cas des cylindres
1182 :solide: solide SHAPER à traiter
1183 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1184 :n_recur: niveau de récursivité
1187 :face: la face médiane
1190 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1191 blabla = "\nDans {} :\n".format(nom_fonction)
1194 if self._verbose_max:
1196 print_tab (n_recur, "face_1 : ", caract_face_1)
1197 print_tab (n_recur, "face_2 : ", caract_face_2)
1199 # Caractéristiques des cylindres
1200 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 )
1202 # Contrôle de la validité de l'épaisseur
1203 erreur = self._verif_epaisseur ( epaisseur )
1205 # Création de la face
1207 face = self._cree_face_mediane_cylindre_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur )
1209 self._couleur_objet (solide, coul_r=0, coul_g=0, coul_b=255)
1214 #=========================== Fin de la méthode ==================================
1216 #=========================== Début de la méthode =================================
1218 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1219 """Crée la face médiane entre deux autres - cas des cylindres
1221 Décodage des caractéristiques
1224 :solide: l'objet solide à traiter
1225 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1226 :n_recur: niveau de récursivité
1229 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1230 :axe_x, axe_y, axe_z: coordonnées de l'axe
1231 :rayon: rayon moyen entre les deux faces
1232 :hauteur: hauteur du cylindre
1233 :epaisseur: épaisseur de l'interface entre les deux faces
1236 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1237 blabla = "\nDans {} :\n".format(nom_fonction)
1239 if self._verbose_max:
1241 print_tab (n_recur, "face_1 : ", caract_face_1)
1242 print_tab (n_recur, "face_2 : ", caract_face_2)
1244 # Coordonnées du centre de la base
1245 coo_x = caract_face_1[2][1]
1246 coo_y = caract_face_1[2][2]
1247 coo_z = caract_face_1[2][3]
1248 # Coordonnées de l'axe
1249 axe_x = caract_face_1[2][4]
1250 axe_y = caract_face_1[2][5]
1251 axe_z = caract_face_1[2][6]
1253 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1254 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1255 l_diag = self._calcul_boite_englobante ( solide, n_recur )
1256 hauteur = 10.*l_diag
1257 if self._verbose_max:
1258 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1260 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1262 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1264 #=========================== Fin de la méthode ==================================
1266 #=========================== Début de la méthode =================================
1268 def _cree_face_mediane_cylindre_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur ):
1269 """Crée la face médiane entre deux autres - cas des cylindres
1271 Création des objets temporaires et de la face externe du cylindre support
1274 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1275 :axe_x, axe_y, axe_z: coordonnées de l'axe
1276 :rayon: rayon moyen entre les deux faces
1277 :hauteur: hauteur du cylindre
1280 :face: la face médiane
1282 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1283 blabla = "\nDans {} :\n".format(nom_fonction)
1285 # Les caractéristiques du cylindre à créer
1286 if self._verbose_max:
1288 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1289 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1290 texte += "Rayon : {}\n".format(rayon)
1291 texte += "Hauteur : {}".format(hauteur)
1294 # Création du point central
1295 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1296 nom_centre = "{}_centre".format(self.nom_solide)
1297 centre.result().setName(nom_centre)
1300 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1301 nom_axe = "{}_axe".format(self.nom_solide)
1302 axe.result().setName(nom_axe)
1304 # Création du plan perpendiculaire à l'axe
1305 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), True)
1306 nom_plan = "{}_plan".format(self.nom_solide)
1307 plan.result().setName(nom_plan)
1309 # Création d'un sketch
1310 nom_par_1 = "{}_R".format(self.nom_solide)
1311 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1312 nom_par_2 = "{}_H".format(self.nom_solide)
1313 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(hauteur))
1315 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1317 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1318 SketchPoint_1 = SketchProjection_1.createdFeature()
1320 SketchCircle_1 = sketch.addCircle(0., 0., rayon)
1321 sketch.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
1322 sketch.setRadius(SketchCircle_1.results()[1], nom_par_1)
1324 nom_sketch = "{}_esquisse".format(self.nom_solide)
1325 sketch.setName(nom_sketch)
1326 sketch.result().setName(nom_sketch)
1328 # Création du cylindre complet
1329 cylindre = model.addExtrusion(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))], model.selection(), nom_par_2, nom_par_2, "Edges")
1330 nom_cylindre = "{}_cylindre".format(self.nom_solide)
1331 cylindre.setName(nom_cylindre)
1332 cylindre.result().setName(nom_cylindre)
1333 cylindre.result().setColor(85, 0, 255)
1335 # Intersection de la face cylindrique avec le solide initial
1336 face = self._creation_face_inter ( nom_cylindre )
1340 #=========================== Fin de la méthode ==================================
1342 #=========================== Début de la méthode =================================
1344 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1345 """Crée la face médiane entre deux autres - cas des sphères
1348 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1349 :n_recur: niveau de récursivité
1352 :face: la face médiane
1355 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1356 blabla = "\nDans {} :".format(nom_fonction)
1359 if self._verbose_max:
1361 print_tab (n_recur, "face_1 : ", caract_face_1)
1362 print_tab (n_recur, "face_2 : ", caract_face_2)
1364 # Caractéristiques des sphères
1365 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1367 # Contrôle de la validité de l'épaisseur
1368 erreur = self._verif_epaisseur ( epaisseur )
1370 # Création de la face
1372 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1378 #=========================== Fin de la méthode ==================================
1380 #=========================== Début de la méthode =================================
1382 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1383 """Crée la face médiane entre deux autres - cas des sphères
1385 Décodage des caractéristiques
1388 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1389 :n_recur: niveau de récursivité
1392 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1393 :rayon: rayon moyen entre les deux faces
1394 :epaisseur: épaisseur de l'interface entre les deux faces
1397 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1398 blabla = "\nDans {} :".format(nom_fonction)
1401 if self._verbose_max:
1403 print_tab (n_recur, "face_1 : ", caract_face_1)
1404 print_tab (n_recur, "face_2 : ", caract_face_2)
1406 # Coordonnées du centre de la sphère
1407 coo_x = caract_face_1[2][1]
1408 coo_y = caract_face_1[2][2]
1409 coo_z = caract_face_1[2][3]
1411 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1413 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1415 return coo_x, coo_y, coo_z, rayon, epaisseur
1417 #=========================== Fin de la méthode ==================================
1419 #=========================== Début de la méthode =================================
1421 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1422 """Crée la face médiane entre deux autres - cas des sphères
1424 Création des objets temporaires et de la face externe de la sphère support
1427 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1428 :rayon: rayon moyen entre les deux faces
1431 :face: la face externe de la sphère support
1434 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1435 blabla = "\nDans {} :\n".format(nom_fonction)
1437 # Les caractéristiques de la sphère à créer
1438 if self._verbose_max:
1440 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1441 texte += "Rayon : {}".format(rayon)
1444 # Création du point central
1445 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1446 nom_centre = "{}_centre".format(self.nom_solide)
1447 centre.result().setName(nom_centre)
1449 # Création d'un plan passant par ce centre et cet axe
1450 plan = model.addPlane(self.part_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", nom_centre), False)
1451 nom_plan = "{}_plan".format(self.nom_solide)
1452 plan.result().setName(nom_plan)
1454 # Création d'un sketch
1455 nom_par_1 = "{}_R".format(self.nom_solide)
1456 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1458 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1460 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1461 SketchPoint_1 = SketchProjection_1.createdFeature()
1463 ### Create SketchArc
1464 SketchArc_1 = sketch.addArc(coo_x, coo_y, coo_x-rayon, coo_y, coo_x+rayon, coo_y, False)
1465 sketch.setRadius(SketchArc_1.results()[1], nom_par_1)
1466 sketch.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
1468 ### Create SketchLine
1469 SketchLine_1 = sketch.addLine(coo_x-rayon, coo_y, coo_x+rayon, coo_y)
1470 nom_ligne = "{}_ligne".format(self.nom_solide)
1471 SketchLine_1.setName(nom_ligne)
1472 SketchLine_1.result().setName(nom_ligne)
1473 SketchLine_1.setAuxiliary(True)
1474 sketch.setHorizontal(SketchLine_1.result())
1475 sketch.setCoincident(SketchArc_1.startPoint(), SketchLine_1.startPoint())
1476 sketch.setCoincident(SketchArc_1.endPoint(), SketchLine_1.endPoint())
1477 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result())
1480 nom_sketch = "{}_esquisse".format(self.nom_solide)
1481 sketch.setName(nom_sketch)
1482 sketch.result().setName(nom_sketch)
1484 # Création de la sphère complète
1485 sphere = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", "{}/{}".format(nom_sketch,nom_ligne)), 360, 0, "Edges")
1486 nom_sphere = "{}_sphere".format(self.nom_solide)
1487 sphere.setName(nom_sphere)
1488 sphere.result().setName(nom_sphere)
1489 sphere.result().setColor(85, 0, 255)
1491 # Intersection de la face sphérique avec le solide initial
1492 face = self._creation_face_inter ( nom_sphere )
1496 #=========================== Fin de la méthode ==================================
1498 #=========================== Début de la méthode =================================
1500 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1501 """Crée la face médiane entre deux autres - cas des tores
1504 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1505 :n_recur: niveau de récursivité
1508 :face: la face médiane
1511 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1512 blabla = "\nDans {} :".format(nom_fonction)
1515 if self._verbose_max:
1517 print_tab (n_recur, "face_1 : ", caract_face_1)
1518 print_tab (n_recur, "face_2 : ", caract_face_2)
1520 # Caractéristiques des tores
1521 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 )
1523 # Contrôle de la validité de l'épaisseur (bidon)
1524 erreur = self._verif_epaisseur ( EP_MIN*10. )
1526 # Création de la face
1528 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1534 #=========================== Fin de la méthode ==================================
1536 #=========================== Début de la méthode =================================
1538 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1539 """Crée la face médiane entre deux autres - cas des tores
1541 Décodage des caractéristiques
1544 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1545 :n_recur: niveau de récursivité
1548 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1549 :axe_x, axe_y, axe_z: coordonnées de l'axe
1550 :rayon_1 : rayon principal
1551 :rayon_2 : rayon secondaire
1554 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1555 blabla = "\nDans {} :".format(nom_fonction)
1558 if self._verbose_max:
1560 print_tab (n_recur, "face_1 : ", caract_face_1)
1561 print_tab (n_recur, "face_2 : ", caract_face_2)
1563 # Coordonnées du centre du tore
1564 coo_x = caract_face_1[2][1]
1565 coo_y = caract_face_1[2][2]
1566 coo_z = caract_face_1[2][3]
1567 # Coordonnées de l'axe
1568 axe_x = caract_face_1[2][4]
1569 axe_y = caract_face_1[2][5]
1570 axe_z = caract_face_1[2][6]
1572 rayon_1 = caract_face_2[2][7]
1573 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1575 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1577 #=========================== Fin de la méthode ==================================
1579 #=========================== Début de la méthode =================================
1581 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1582 """Crée la face médiane entre deux autres - cas des tores
1584 Création des objets temporaires et de la face externe du tore support
1587 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1588 :axe_x, axe_y, axe_z: coordonnées de l'axe
1589 :rayon_1 : rayon principal
1590 :rayon_2 : rayon secondaire
1593 :face: la face externe du tore support
1596 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1597 blabla = "\nDans {} :\n".format(nom_fonction)
1600 if self._verbose_max:
1602 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1603 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1604 texte += "Rayon principal : {}\n".format(rayon_1)
1605 texte += "Rayon secondaire : {}".format(rayon_2)
1608 # Création du point central
1609 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1610 nom_centre = "{}_centre".format(self.nom_solide)
1611 centre.result().setName(nom_centre)
1614 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1615 nom_axe = "{}_axe".format(self.nom_solide)
1616 axe.result().setName(nom_axe)
1618 # Création d'un plan passant par ce centre et cet axe
1619 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1620 nom_plan = "{}_plan".format(self.nom_solide)
1621 plan.result().setName(nom_plan)
1623 # Création d'un sketch
1624 nom_par_1 = "{}_R_1".format(self.nom_solide)
1625 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1626 nom_par_2 = "{}_R_2".format(self.nom_solide)
1627 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1629 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1631 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1632 SketchPoint_1 = SketchProjection_1.createdFeature()
1634 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1635 SketchLine_1 = SketchProjection_2.createdFeature()
1637 SketchPoint_2 = sketch.addPoint(rayon_1, 0.)
1638 sketch.setDistance(SketchPoint_1.result(), SketchPoint_2.coordinates(), nom_par_1, True)
1640 SketchLine_2 = sketch.addLine(0., 0., rayon_1, 0.)
1641 SketchLine_2.setAuxiliary(True)
1642 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1643 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_2.endPoint())
1644 sketch.setPerpendicular(SketchLine_1.result(), SketchLine_2.result())
1646 SketchCircle_1 = sketch.addCircle(0., 0., rayon_2)
1647 sketch.setCoincident(SketchPoint_2.result(), SketchCircle_1.center())
1648 sketch.setRadius(SketchCircle_1.results()[1], nom_par_2)
1651 nom_sketch = "{}_esquisse".format(self.nom_solide)
1652 sketch.setName(nom_sketch)
1653 sketch.result().setName(nom_sketch)
1655 # Création du tore complet
1656 nom_tore = "{}_tore".format(self.nom_solide)
1657 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_tore )
1659 # Intersection de la face torique avec le solide initial
1660 face = self._creation_face_inter ( nom_tore )
1664 #=========================== Fin de la méthode ==================================
1666 #=========================== Début de la méthode =================================
1668 def _cree_face_mediane_cone ( self, geompy, caract_face_1, caract_face_2, n_recur ):
1669 """Crée la face médiane entre deux autres - cas des cones
1672 :geompy: environnement de GEOM
1673 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1674 :n_recur: niveau de récursivité
1677 :face: la face médiane
1680 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1681 blabla = "\nDans {} :".format(nom_fonction)
1684 if self._verbose_max:
1686 print_tab (n_recur, "face_1 : ", caract_face_1)
1687 print_tab (n_recur, "face_2 : ", caract_face_2)
1689 # Caractéristiques des cones
1690 coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur = self._cree_face_mediane_cone_0 ( geompy, caract_face_1, caract_face_2 )
1692 # Contrôle de la validité de l'épaisseur (bidon)
1693 erreur = self._verif_epaisseur ( EP_MIN*10. )
1695 # Création de la face
1697 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1703 #=========================== Fin de la méthode ==================================
1705 #=========================== Début de la méthode =================================
1707 def _cree_face_mediane_cone_0 ( self, geompy, caract_face_1, caract_face_2, n_recur ):
1708 """Crée la face médiane entre deux autres - cas des cones
1710 Décodage des caractéristiques
1713 :geompy: environnement de GEOM
1714 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1715 :n_recur: niveau de récursivité
1718 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1719 :axe_x, axe_y, axe_z: coordonnées de l'axe
1720 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1721 :hauteur: hauteur du cone
1724 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1725 blabla = "\nDans {} :".format(nom_fonction)
1728 if self._verbose_max:
1730 print_tab (n_recur, "face_1 : ", caract_face_1)
1731 print_tab (n_recur, "face_2 : ", caract_face_2)
1733 # Coordonnées du centre de la base
1734 coo_x = caract_face_1[2][1]
1735 coo_y = caract_face_1[2][2]
1736 coo_z = caract_face_1[2][3]
1737 # Coordonnées de l'axe
1738 axe_x = caract_face_1[2][4]
1739 axe_y = caract_face_1[2][5]
1740 axe_z = caract_face_1[2][6]
1742 # Pour un cone complet, les caractéristiques fournies par GEOM sont correctes
1743 # Mais s'il est découpé, malheureusement,bug dans GEOM et caract_face_2[2][8] est toujours nul !
1744 # Alors on passe par le décodage des arêtes
1745 #rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1746 #rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1747 caract_arete_face_1 = self._calcul_caract_aretes_face ( geompy, caract_face_1 )
1748 caract_arete_face_2 = self._calcul_caract_aretes_face ( geompy, caract_face_2 )
1751 for caract_aretes_face in [caract_arete_face_1,caract_arete_face_2]:
1753 for l_aux in caract_aretes_face:
1754 if ( l_aux[0] in ( geompy.kind.CIRCLE, geompy.kind.ARC_CIRCLE ) ):
1755 #print ("R =",l_aux[7])
1764 hauteur = caract_face_1[2][9]
1766 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1768 #=========================== Fin de la méthode ==================================
1770 #=========================== Début de la méthode =================================
1772 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1773 """Crée la face médiane entre deux autres - cas des cones
1775 Création des objets temporaires et de la face externe du cone support
1778 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1779 :axe_x, axe_y, axe_z: coordonnées de l'axe
1780 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1781 :hauteur: hauteur du cone
1784 :face: la face externe du cone support
1786 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1787 blabla = "\nDans {} :\n".format(nom_fonction)
1790 if self._verbose_max:
1792 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1793 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1794 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1795 texte += "Hauteur : {}".format(hauteur)
1798 # Création du point central
1799 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1800 nom_centre = "{}_centre".format(self.nom_solide)
1801 centre.result().setName(nom_centre)
1804 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1805 nom_axe = "{}_axe".format(self.nom_solide)
1806 axe.result().setName(nom_axe)
1808 # Création d'un plan passant par ce centre et cet axe
1809 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1810 nom_plan = "{}_plan".format(self.nom_solide)
1811 plan.result().setName(nom_plan)
1813 # Création d'un sketch
1814 nom_par_1 = "{}_R_1".format(self.nom_solide)
1815 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1816 nom_par_2 = "{}_R_2".format(self.nom_solide)
1817 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1818 nom_par_3 = "{}_H".format(self.nom_solide)
1819 model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
1821 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1823 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1824 SketchPoint_1 = SketchProjection_1.createdFeature()
1826 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1827 SketchLine_1 = SketchProjection_2.createdFeature()
1829 SketchLine_2 = sketch.addLine(coo_x, coo_y, coo_x+rayon_1, coo_y+hauteur)
1830 SketchLine_2.setAuxiliary(True)
1831 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1832 sketch.setParallel(SketchLine_1.result(), SketchLine_2.result())
1833 sketch.setLength(SketchLine_2.result(), nom_par_3)
1835 SketchLine_3 = sketch.addLine(coo_x+rayon_1, coo_y, coo_x+rayon_1, coo_y+hauteur)
1836 sketch.setDistance(SketchLine_2.startPoint(), SketchLine_3.result(), nom_par_1, True)
1837 sketch.setDistance(SketchLine_2.endPoint(), SketchLine_3.result(), nom_par_2, True)
1838 sketch.setLength(SketchLine_3.result(), "2.5*{}".format(nom_par_3))
1840 SketchPoint_2 = sketch.addPoint(coo_x, coo_y)
1841 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_3.result())
1842 sketch.setMiddlePoint(SketchPoint_2.coordinates(), SketchLine_3.result())
1844 SketchLine_4 = sketch.addLine(coo_x, coo_y, 1.2*coo_x, 1.2*coo_y)
1845 SketchLine_4.setAuxiliary(True)
1846 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.startPoint())
1847 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_4.endPoint())
1848 sketch.setHorizontal(SketchLine_4.result())
1851 nom_sketch = "{}_esquisse".format(self.nom_solide)
1852 sketch.setName(nom_sketch)
1853 sketch.result().setName(nom_sketch)
1855 # Création du cone complet
1856 nom_cone = "{}_cone".format(self.nom_solide)
1857 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
1859 # Intersection de la face conique avec le solide initial
1860 face = self._creation_face_inter ( nom_cone )
1864 #=========================== Fin de la méthode ==================================
1866 #=========================== Début de la méthode =================================
1868 def _calcul_boite_englobante ( self, objet, n_recur ):
1869 """Crée la hauteur englobant à coup sûr l'objet
1872 :objet: l'objet à traiter
1873 :n_recur: niveau de récursivité
1876 :l_diag: longueur de la diagonale de la boîte englobante
1879 nom_fonction = __name__ + "/_calcul_boite_englobante"
1880 blabla = "\nDans {} :".format(nom_fonction)
1882 if self._verbose_max:
1885 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1886 if self._verbose_max:
1887 print_tab (n_recur, "Création de la boite englobante pour l'objet ", objet.name())
1888 print_tab (n_recur, "de type ", objet.shapeType())
1889 #print ('bbox = model.getBoundingBox(self.part_doc, model.selection("{}", "{}"))'.format(objet.shapeType(),objet.name()))
1890 bbox = model.getBoundingBox(self.part_doc, model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
1892 bbox_nom = bbox.name()
1893 if self._verbose_max:
1894 print_tab (n_recur, "Boîte englobante : '{}' '{}'".format(bbox.name(), bbox.result().name()))
1896 if self._verbose_max:
1897 coo_min = model.getPointCoordinates(self.part_doc, \
1898 model.selection("VERTEX", "[{}_1/Back][{}_1/Left][{}_1/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)))
1899 coo_max = model.getPointCoordinates(self.part_doc, \
1900 model.selection("VERTEX", "[{}_1/Front][{}_1/Right][{}_1/Top]".format(bbox_nom,bbox_nom,bbox_nom)))
1901 texte = "Xmin = {}, Xmax = {}\n".format(coo_min[0],coo_max[0])
1902 texte += "\tYmin = {}, Ymax = {}\n".format(coo_min[1],coo_max[1])
1903 texte += "\tZmin = {}, Zmax = {}".format(coo_min[2],coo_max[2])
1904 print_tab (n_recur, texte)
1906 l_diag = model.measureDistance(self.part_doc, \
1907 model.selection("VERTEX", "[{}_1/Back][{}_1/Left][{}_1/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)), \
1908 model.selection("VERTEX", "[{}_1/Front][{}_1/Right][{}_1/Top]".format(bbox_nom,bbox_nom,bbox_nom)) )
1909 if self._verbose_max:
1910 print_tab (n_recur, "Longueur de la diagonale : ", l_diag)
1914 #=========================== Fin de la méthode ==================================
1916 #=========================== Début de la méthode =================================
1918 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
1919 """Crée un volume de révolution
1922 :nom_sketch: nom du sketch à révolutionner
1923 :nom_centre: nom du point associé au centre du volume de révolution
1924 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1925 :axe_x, axe_y, axe_z: coordonnées de l'axe
1926 :rayon_1 : rayon principal
1927 :rayon_2 : rayon secondaire
1928 :nom_objet: nom de l'objet 2D créé
1931 nom_fonction = __name__ + "/_cree_revolution"
1932 blabla = "\nDans {} :\n".format(nom_fonction)
1934 if self._verbose_max:
1936 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1937 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1940 # Création d'un point décalé par rapport au point central
1941 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
1942 nom_point = "{}_point".format(self.nom_solide)
1943 point.result().setName(nom_point)
1945 # Création de l'axe de la rotation
1946 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
1947 nom_axe_r = "{}_axe_r".format(self.nom_solide)
1948 axe_r.result().setName(nom_axe_r)
1950 # Création de l'objet complet
1951 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
1952 objet.setName(nom_objet)
1953 objet.result().setName(nom_objet)
1954 objet.result().setColor(85, 0, 255)
1958 #=========================== Fin de la méthode ==================================
1960 #=========================== Début de la méthode =================================
1962 def _creation_face_inter ( self, nom_objet ):
1963 """Crée la face par intersection entre l'objet initial et une face complète
1965 . Repère la face principale de l'objet support
1966 . Réalise l'intersection avec le solide initial
1969 :nom_objet: nom de l'objet 2D créé
1972 :face: la face externe de l'objet support intersecté avec le solide initial
1975 nom_fonction = __name__ + "/_creation_face_inter"
1976 blabla = "\nDans {} :\n".format(nom_fonction)
1978 if self._verbose_max:
1981 face = model.addCommon(self.part_doc, [model.selection("SOLID", self.nom_solide_aux), model.selection("FACE", nom_objet)], keepSubResults = True)
1985 #=========================== Fin de la méthode ==================================
1987 #=========================== Début de la méthode =================================
1989 def face_mediane_solide (self, solide, geompy, objet_geom, n_recur=0):
1990 """Calcul de la face médiane pour un solide
1993 :solide: solide SHAPER à traiter
1994 :geompy: environnement de GEOM
1995 :objet_geom: l'objet solide à traiter au format GEOM
1996 :n_recur: niveau de récursivité
1999 :erreur: code d'erreur
2000 :message: message d'erreur
2003 nom_fonction = __name__ + "/face_mediane_solide"
2004 blabla = "\nDans {} :\n".format(nom_fonction)
2006 if self._verbose_max:
2009 print_tab (n_recur, "Traitement du solide ", solide.name())
2018 # 2. Explosion du solide en faces
2020 erreur, message, l_faces_geom, l_faces = self._faces_du_solide ( geompy, objet_geom, solide, n_recur )
2024 # 3. Calcul des caractéristiques géométriques des faces
2026 tb_caract = self._calcul_caract_faces ( geompy, l_faces_geom )
2028 # 4. Tri des faces en fonction de leurs caractéristiques géométriques
2030 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract )
2034 # 5. Création de la face médiane
2036 erreur, face = self._cree_face_mediane ( solide, geompy, caract_face_1, caract_face_2, n_recur )
2040 # 6. Exportation step
2042 if self._export_step:
2043 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2044 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2045 export.execute(True)
2052 if ( erreur and self._verbose_max ):
2053 print (blabla, message)
2055 return erreur, message
2057 #=========================== Fin de la méthode ==================================
2059 #=========================== Début de la méthode =================================
2061 def _traitement_objet (self, solide=None, objet_geom=None, n_recur=0):
2062 """Traitement d'un objet
2065 :solide: solide SHAPER à traiter
2066 :objet_geom: l'objet GEOM équivalent
2067 :n_recur: niveau de récursivité
2070 :erreur: code d'erreur
2071 :message: message d'erreur
2074 nom_fonction = __name__ + "/_traitement_objet"
2075 blabla = "\nDans {} :".format(nom_fonction)
2077 if self._verbose_max:
2079 print_tab (n_recur, "solide = " , solide)
2080 print_tab (n_recur, "objet_geom = ", objet_geom)
2091 if self.affiche_aide_globale :
2094 # 3. Les imports pour salomé
2095 geompy = geomBuilder.New()
2097 # 4. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2098 # Attention à ne pas recréer le répertoire à chaque fois
2099 if self._export_step:
2101 if self._verbose_max:
2102 print_tab (n_recur, "Préparation de l'export STEP")
2104 if self.rep_step is None:
2105 if self.ficcao is None:
2106 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2108 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2109 if os.path.isdir(self.rep_step):
2110 l_aux = os.listdir(self.rep_step)
2111 for nomfic in l_aux:
2112 os.remove(os.path.join(self.rep_step,nomfic))
2114 os.mkdir(self.rep_step)
2115 if self._verbose_max:
2116 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2118 # 5. Calcul réel de la face médiane
2121 self.nom_solide = objet_geom.GetName()
2123 erreur, message = self.face_mediane_solide (solide, geompy, objet_geom, n_recur)
2129 return erreur, message
2131 #=========================== Fin de la méthode ==================================
2133 #=========================== Début de la méthode =================================
2135 def surf_fic_cao (self, ficcao, nom_objet=None):
2136 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2139 :ficcao: fichier de l'objet à traiter
2140 :nom_objet: un nom à donner à l'objet à traiter
2143 :erreur: code d'erreur
2144 :message: message d'erreur
2147 nom_fonction = __name__ + "/surf_fic_cao"
2148 blabla = "\nDans {} :\n".format(nom_fonction)
2150 if self._verbose_max:
2160 # 1. Définition de la pièce
2162 self.part_doc = model.activeDocument()
2163 if ( self.part_doc.kind() == "PartSet" ):
2164 part = model.addPart(self.part_doc)
2165 self.part_doc = part.document()
2167 # 2. Import de la CAO
2169 self.ficcao = ficcao
2170 print ("Traitement du fichier {}".format(ficcao))
2172 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2176 # 3. Calcul des surfaces
2178 erreur, message = self.surf_objet_shaper ( objet )
2187 if ( erreur and self._verbose_max ):
2188 print (blabla, message)
2190 return erreur, message
2192 #=========================== Fin de la méthode ==================================
2194 #=========================== Début de la méthode =================================
2196 def surf_objet_shaper (self, objet):
2197 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2200 :objet: objet à traiter
2203 :erreur: code d'erreur
2204 :message: message d'erreur
2207 nom_fonction = __name__ + "/surf_objet_shaper"
2208 blabla = "Dans {} :".format(nom_fonction)
2210 if self._verbose_max or True:
2213 # 1. Acquisition de la liste des noms des sous-objets solides
2215 self.d_statut_so = dict()
2216 self.l_noms_so = list()
2217 self.l_faces_m = list()
2219 _ = self._nom_sous_objets (objet, True)
2220 if self._verbose_max:
2221 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2223 # 2. Les faces médianes
2225 erreur, message = self._surf_objet_shaper_0 ( objet )
2227 # 3. Gestion des faces créées
2229 #self._surf_objet_shaper_1 ( )
2231 # 4. Futur message pour le résultat
2233 if ( self._export_step and not erreur ):
2234 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2236 return erreur, message
2238 #=========================== Fin de la méthode ==================================
2240 #=========================== Début de la méthode =================================
2242 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2243 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2246 :objet: objet à traiter
2247 :n_recur: niveau de récursivité
2250 :erreur: code d'erreur
2251 :message: message d'erreur
2254 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2255 blabla = "Dans {} :\n".format(nom_fonction)
2257 if self._verbose_max or True:
2259 for _ in range(n_recur):
2261 texte = "\n{}{}".format(prefixe,blabla)
2262 texte += "{}n_recur = {}".format(prefixe,n_recur)
2270 # 1. Au premier passage, il faut récupérer la pièce et garder la référence au résultat principal
2272 if ( n_recur == 0 ):
2273 self.part_doc = model.activeDocument()
2274 objet_0 = objet.result()
2275 self.objet_principal = objet_0
2276 objet_bis = objet.defaultResult().shape()
2277 print_tab (n_recur, "Examen de l'objet ", objet.result().name(), saut_av=True)
2278 print_tab (n_recur, "Type python : ", type(objet))
2279 print_tab (n_recur, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2281 exp = GeomAPI_ShapeExplorer(objet_bis, GeomAPI_Shape.SOLID)
2283 l_volumes.append(exp.current().solid())
2286 for ivolume, volume in enumerate(l_volumes):
2287 print_tab (n_recur+1, "Type python : ", type(volume))
2288 print_tab (n_recur+1, "Volume n°{} ; volume = ".format(ivolume), GeomAlgoAPI_ShapeTools.volume(volume))
2289 print_tab (n_recur+1, "Type {} / ".format(volume.shapeType()), volume.shapeTypeStr())
2290 #print ("\tInformations : {}".format(volume.shapeInfo()))
2293 exp = GeomAPI_ShapeExplorer(volume, GeomAPI_Shape.FACE)
2295 l_faces.append(exp.current().face())
2298 for iface, face in enumerate(l_faces):
2299 print_tab (n_recur+2, "Face n°{} ; surface = ".format(iface), GeomAlgoAPI_ShapeTools.area(face))
2302 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2303 print_tab (n_recur, "Type python : ", type(objet))
2304 print_tab (n_recur, "Type ", objet.shapeType())
2306 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2308 nb_sub_results = objet_0.numberOfSubs()
2310 if self._verbose_max or True:
2311 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType())
2312 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2314 for n_sobj in range(nb_sub_results):
2316 # 2.1. Exploration récursive de l'arborescence
2318 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2322 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2324 if ( objet_0.shapeType() == "SOLID" ):
2325 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2332 # 3. Futur message pour le résultat
2334 if self._export_step:
2335 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2339 return erreur, message
2341 #=========================== Fin de la méthode ==================================
2343 #=========================== Début de la méthode =================================
2345 def _surf_objet_shaper_1 (self):
2346 """Gestion des surfaces médianes créées
2349 :erreur: code d'erreur
2350 :message: message d'erreur
2353 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2354 blabla = "Dans {} :\n".format(nom_fonction)
2356 if self._verbose_max:
2359 # 1. Informations sur les faces à problème
2361 if self.faces_pb_nb:
2362 if ( self.faces_pb_nb == 1 ):
2363 texte = "1 face pose"
2365 texte = "{} faces posent".format(self.faces_pb_nb)
2366 print ("\n{} problème.\n{}".format(texte,self.faces_pb_msg))
2368 # 2. Si plus d'une face a été créée
2369 if ( len(self.l_faces_m) > 1 ):
2371 # 2.1. Partition du paquet de faces
2373 if self._verbose_max:
2374 print ("Partitionnnement des faces créées.")
2377 for (face,_) in self.l_faces_m:
2378 l_objets.append(model.selection("COMPOUND", "all-in-{}".format(face.name())))
2380 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2382 Partition_1.result().setName("{}_M".format(self.objet_principal.name()))
2383 for iaux, (face,_) in enumerate(self.l_faces_m):
2384 Partition_1.result().subResult(iaux).setName("{}".format(face.name()))
2385 self._couleur_objet (Partition_1, coul_r=0, coul_g=170, coul_b=0)
2387 # 2.2. Récupération des faces individuelles
2389 if self._verbose_max:
2390 print ("Récupération des faces individuelles.")
2393 for iaux, (face,_) in enumerate(self.l_faces_m):
2394 l_objets.append(face.result())
2396 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2397 for iaux, (face,_) in enumerate(self.l_faces_m):
2398 Recover_1.results()[iaux].setName("{}".format(face.name()))
2399 Recover_1.results()[iaux].setColor(0, 170, 0)
2401 # 2.3. Mise en dossier
2403 if self._verbose_max:
2404 print ("Mise en dossier.")
2406 for (face,fonction_0) in self.l_faces_m:
2407 dossier = model.addFolder(self.part_doc, fonction_0, face)
2408 dossier.setName(face.name()[:-2])
2412 #=========================== Fin de la méthode ==================================
2414 #=========================== Début de la méthode =================================
2416 def surf_solide_shaper (self, solide, n_recur):
2417 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2420 :solide: solide SHAPER à traiter
2421 :n_recur: numéro de la récurrence
2424 :erreur: code d'erreur
2425 :message: message d'erreur
2428 nom_fonction = __name__ + "/surf_solide_shaper"
2429 blabla = "Dans {} :".format(nom_fonction)
2431 if self._verbose_max or True:
2439 self.nom_solide = solide.name()
2440 if self._verbose_max or True:
2441 print_tab (n_recur, "solide", self.nom_solide)
2443 # 1. Isolement du solide
2444 solide_aux, recover = self._isole_solide ( solide, n_recur )
2446 # 2. Exportation dans un fichier step pour traitement dans GEOM
2448 fichier = tempfile.mkstemp(suffix=".stp")[1]
2449 if self._verbose_max:
2450 print_tab (n_recur, "fichier = ", fichier)
2451 print_tab (n_recur, "solide = ", solide_aux.name())
2452 print_tab (n_recur, "de type = ", solide_aux.shapeType())
2453 export = model.exportToFile(self.part_doc, fichier, [model.selection(solide_aux.shapeType(), solide_aux.name())])
2454 export.execute(True)
2457 taille = os.path.getsize(fichier)
2459 message = "Export de SHAPER vers GEOM impossible pour le solide '{}' de type '{}'\n".format(solide_aux.name(), solide_aux.shapeType())
2460 message += "Le fichier {} est de taille {}".format(fichier,taille)
2464 # 3. Importation dans GEOM
2465 geompy = geomBuilder.New()
2466 objet_geom = geompy.ImportSTEP(fichier, False, True)
2469 # 4. Traitement de l'objet correspondant
2470 erreur, message = self._traitement_objet ( solide=solide_aux, objet_geom=objet_geom, n_recur=n_recur )
2472 if ( erreur and self._verbose_max ):
2473 print (blabla, message)
2475 # 5. Mise en forme de l'objet principal récupéré
2476 if ( recover is not None ):
2477 _ = self._nom_sous_objets (recover, False)
2479 # 6. Neutralisation des erreurs dues à l'épaisseur
2480 if ( erreur in (-2,-1,2) ):
2486 return erreur, message
2488 #=========================== Fin de la méthode ==================================
2490 #=========================== Début de la méthode =================================
2492 def surf_objet_geom (self, objet_geom):
2493 """Calcule la surface médiane pour un objet GEOM passé en argument
2496 :objet_geom: l'objet GEOM à traiter
2499 :erreur: code d'erreur
2500 :message: message d'erreur
2503 nom_fonction = __name__ + "/surf_objet_geom"
2504 blabla = "\nDans {} :\n".format(nom_fonction)
2506 if self._verbose_max:
2509 erreur, message = self._traitement_objet ( objet_geom=objet_geom )
2511 if ( erreur and self._verbose_max ):
2512 print (blabla, message)
2514 return erreur, message
2516 #=========================== Fin de la méthode ==================================
2518 #=========================== Début de la méthode =================================
2520 def lancement (self):
2525 :erreur: code d'erreur
2526 :message: message d'erreur
2529 nom_fonction = __name__ + "/lancement"
2530 blabla = "\nDans {} :\n".format(nom_fonction)
2532 if self._verbose_max:
2535 erreur, message = self._traitement_objet ( )
2537 if ( erreur and self._verbose_max ):
2538 print (blabla, message)
2540 return erreur, message
2542 #=========================== Fin de la méthode ==================================
2544 #========================== Fin de la classe ====================================
2546 #==================================================================================
2548 #==================================================================================
2550 if __name__ == "__main__" :
2552 HOME_SH_SM_EXCHANGE = os.environ["HOME_SH_SM_EXCHANGE"]
2554 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "Solid_7.step"))
2555 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Objet_1.stp"))
2556 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval_007.stp"))
2557 ##L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval.stp"))
2558 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2.step"))
2559 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_22.step"))
2560 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_5.step"))
2561 L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Observatoire.stp"))
2563 for FIC_CAO in L_FIC_CAO:
2568 #L_OPTIONS.append("-h")
2569 #L_OPTIONS.append("-v")
2570 L_OPTIONS.append("-vmax")
2571 #L_OPTIONS.append("-export_step")
2573 # 2. Lancement de la classe
2575 #print ("L_OPTIONS :", L_OPTIONS)
2577 SURFACE_MEDIANE = SurfaceMediane(L_OPTIONS)
2578 if SURFACE_MEDIANE.affiche_aide_globale:
2579 sys.stdout.write(SURFACE_MEDIANE.__doc__+"\n")
2582 PARTSET = model.moduleDocument()
2583 _ = model.addPart(PARTSET)
2584 ERREUR, MESSAGE_ERREUR = SURFACE_MEDIANE.surf_fic_cao(FIC_CAO)
2586 MESSAGE_ERREUR += "\n Code d'erreur : %d\n" % ERREUR
2587 sys.stderr.write(MESSAGE_ERREUR)