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.03"
41 #========================= Les imports - Début ===================================
53 from SketchAPI import *
54 from salome.shaper import model
55 from salome.shaper import geom
57 from GeomAlgoAPI import *
61 #========================== Les imports - Fin ====================================
64 D_FMT["stp"] = ["stp", "step"]
65 D_FMT["igs"] = ["igs", "iges"]
66 for CLE in ("brep", "xao"):
69 # statut = 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
88 # Transparence des solides traités correctement
91 # Limite basse de l'épaisseur pour pouvoir faire les intersections
94 #========================= Début de la fonction ==================================
96 def decode_cao (fmt_cao):
97 """Décode le format de la cao
100 :fmt_cao: format du fichier, step, iges, etc.
102 :fmt_cao_0: format décodé
107 fmt_cao_low = fmt_cao.lower()
109 for cle, l_aux in D_FMT.items():
110 if ( fmt_cao_low in l_aux ):
116 #========================= Fin de la fonction ===================================
118 #========================= Début de la fonction ==================================
120 def import_cao (part_doc, ficcao, nom_objet=None, verbose=False):
121 """Importation d'une cao
125 :ficcao: le fichier de la CAO
126 :nom_objet: nom à donner à l'objet lu, éventuellement
128 :objet: l'objet importé dans SHAPER
131 nom_fonction = __name__ + "/import_cao"
132 blabla = "Dans {} :\n".format(nom_fonction)
133 message_0 = "Fichier : {}\n".format(ficcao)
135 message = blabla + message_0
136 message += "nom_objet : {}".format(nom_objet)
144 laux = ficcao.split(".")
145 fmt_cao_0 = decode_cao (laux[-1])
147 if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
148 message += "Le format de CAO est inconnu"
152 message += "Le fichier de CAO n'a pas été décodé correctement."
155 elif not os.path.isfile(ficcao):
156 message += "Le fichier de CAO est inconnu."
162 objet = model.addImport(part_doc, ficcao)
166 if nom_objet is not None:
167 objet.result().setName(nom_objet)
170 texte = "Objet : '{}'\n".format(objet.result().name())
171 texte += "De type : '{}'".format(objet.result().shapeType())
174 return erreur, message, objet
176 #========================= Fin de la fonction ===================================
178 #========================= Début de la fonction ==================================
180 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
181 """Imprime avec des tabulations
184 :nb_tab: nombre de tabulations à appliquer
185 :message: message principal
186 :argu: argument du format
187 :saut_av: saut de ligne avant le texte
188 :saut_ap: saut de ligne après le texte
196 for _ in range(nb_tab):
200 if ( argu is not None ):
201 texte += "{}".format(argu)
208 #========================= Fin de la fonction ===================================
210 #========================= Début de la fonction ==================================
212 def nommage (objet, nom, couleur=None):
213 """Nomme un objet et son résultat
216 :objet: objet à traiter
217 :nom: nom à attribuer
218 :couleur: éventuellement couleur
222 objet.result().setName(nom)
224 if ( couleur is not None ):
225 objet.result().setColor(couleur[0], couleur[1], couleur[2])
227 #========================= Fin de la fonction ===================================
230 #=================================== La classe ===================================
232 class SurfaceMediane (object):
234 """Calcul des surfaces médianes de solides minces
236 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
237 une structure qui est un solide ou un assemblage de solides (compound).
238 Pour réaliser l'opération, trois façons de faire :
240 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
242 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
243 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
245 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
246 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
249 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
250 de taille identique et supérieure aux tailles des autres faces du solide. \
251 Cela fonctionne pour des surfaces planes ou de forme canonique.
252 Il crée alors une surface au milieu de ces deux grandes faces. \
253 Cette face est coloriée en vert, le solide est en vert et transparent.
255 On sait traiter les faces :
262 Si la création n'a pas eu lieu, un message est émis et les solides sont mis en couleur :
263 . Rouge : le solide n'est pas assez mince.
264 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
265 . Orange : la forme de la face n'est pas reconnue.
273 . Exportation finale dans un fichier step. Par défaut, pas d'export.
274 -export_step/-no_export_step
277 surf_fic_cao --> import_cao
278 --> surf_objet_shaper (récursif) --> _nom_sous_objets
279 --> _surf_objet_shaper_0
280 --> surf_solide_shaper --> _isole_solide
281 --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
283 --> _cree_face_mediane
285 _cree_face_mediane --> _cree_face_mediane_plane
286 --> _cree_face_mediane_cylindre
287 --> _cree_face_mediane_sphere
288 --> _cree_face_mediane_tore
289 --> _cree_face_mediane_cone
290 --> _cree_face_mediane_0
299 affiche_aide_globale = 0
306 nom_solide_aux = None
312 objet_principal = None
313 # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
315 # Statut de chaque sous-objet connu par son nom :
316 # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
318 # Liste des faces médianes créées et des fonctions initiales
320 # La fonction initiale
326 #=========================== Début de la méthode =================================
328 def __init__ ( self, liste_option ):
330 """Le constructeur de la classe SurfaceMediane
332 Décodage des arguments
333 On cherche ici les arguments généraux : aide, verbeux
336 for option in liste_option :
339 if isinstance(option,str):
340 saux = option.upper()
342 if saux in ( "-H", "-HELP" ):
343 self.affiche_aide_globale = 1
346 elif saux == "-VMAX" :
348 self._verbose_max = 1
349 elif saux == "-EXPORT_STEP":
350 self._export_step = True
351 elif saux == "-NO_EXPORT_STEP":
352 self._export_step = False
354 #=========================== Fin de la méthode ==================================
356 #=========================== Début de la méthode =================================
359 """A la suppression de l'instance de classe"""
360 if self._verbose_max:
361 print ("Suppression de l'instance de la classe.")
363 #=========================== Fin de la méthode ==================================
365 #=========================== Début de la méthode =================================
367 def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
368 """Gère les noms des sous_objets solides
371 :objet: objet à traiter
372 :lecture: vrai pour lire les noms, faux pour les attribuer
373 :n_recur: niveau de récursivité
374 :rang: rang du sous-objet
377 :rang: rang du sous-objet
380 nom_fonction = __name__ + "/_nom_sous_objets"
381 blabla = "Dans {} :\n".format(nom_fonction)
383 if self._verbose_max:
385 for _ in range(n_recur):
387 texte = "\n{}{}".format(prefixe,blabla)
388 texte += "{}n_recur = {}".format(prefixe,n_recur)
389 texte += "\n{}lecture = {}".format(prefixe,lecture)
392 # 1. Au premier passage, il faut garder la référence au résultat principal
395 objet_0 = objet.result()
396 if self._verbose_max:
397 print ("d_statut_so = {}".format(self.d_statut_so))
401 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
403 nb_sub_results = objet_0.numberOfSubs()
405 if self._verbose_max:
406 texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
407 texte += "de type '{}'".format(objet_0.shapeType())
408 texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
411 for n_sobj in range(nb_sub_results):
413 # 2.1. Exploration récursive de l'arborescence
415 rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
417 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
419 if ( objet_0.shapeType() == "SOLID" ):
420 # A la lecture, on enregistre le nom
423 self.l_noms_so.append(nom)
424 self.d_statut_so[nom] = 0
425 # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
427 nom = self.l_noms_so[rang]
429 etat = self.d_statut_so[nom]
430 objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
432 objet_0.setTransparency (TRANSPARENCE)
437 #=========================== Fin de la méthode ==================================
439 #=========================== Début de la méthode =================================
441 def _couleur_objet (self, objet, n_recur=0, coul_r=1, coul_g=0, coul_b=0):
442 """Appliquer une couleur à un objet et à ses sous_objets
445 :objet: objet à traiter
446 :n_recur: niveau de récursivité
447 :coul_r,coul_g,coul_b: code RGB de la couleur à appliquer
450 :rang: rang du sous-objet
453 nom_fonction = __name__ + "/_couleur_objet"
454 blabla = "Dans {} :".format(nom_fonction)
456 if self._verbose_max:
458 print_tab(n_recur, "objet : ", objet.name())
459 print_tab(n_recur, "RGB = ({},{},{})".format(coul_r,coul_g,coul_b))
461 # 1. Au premier passage, il faut garder la référence au résultat principal
464 objet_0 = objet.result()
468 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
470 nb_sub_results = objet_0.numberOfSubs()
472 if self._verbose_max:
473 print_tab(n_recur, "Examen de l'objet ",objet_0.name())
474 texte = "de type '{}' ".format(objet_0.shapeType())
475 texte += "et de {} sous-objets".format(nb_sub_results)
476 print_tab(n_recur, texte)
478 for n_sobj in range(nb_sub_results):
480 # 2.1. Exploration récursive de l'arborescence
482 self._couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b )
484 # 2.2. Cet objet n'a pas de sous-objets : on le colore
485 if self._verbose_max:
486 print_tab(n_recur, "Couleur affectée à l'objet ",objet_0.name())
487 objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
489 #print ("sortie de {}".format(nom_fonction))
493 #=========================== Fin de la méthode ==================================
495 #=========================== Début de la méthode =================================
497 def _isole_solide ( self, solide, n_recur ):
498 """Isole le solide de son arboresence
501 :solide: le solide à traiter
502 :n_recur: numéro de la récurrence
505 :objet: le solide isolé
506 :recover: la fonction de récupération
509 nom_fonction = __name__ + "/_isole_solide"
510 blabla = "Dans {} :".format(nom_fonction)
511 if self._verbose_max:
512 print_tab (n_recur, blabla)
513 texte = "Pour le solide '{}' ".format(solide.name())
514 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
515 print_tab (n_recur, texte)
517 if ( solide.name() != self.objet_principal.name() ):
518 objet, recover = self._isole_solide_a ( solide, n_recur )
521 objet, recover = self._isole_solide_b ( solide, n_recur )
523 if self._verbose_max:
524 print_tab (n_recur, "objet final : ", objet.name())
525 print_tab (n_recur, "fonction_0 : ", self.fonction_0)
526 print_tab (n_recur, "recover : ", recover)
528 return objet, recover
530 #=========================== Fin de la méthode ==================================
532 #=========================== Début de la méthode =================================
534 def _isole_solide_a ( self, solide, n_recur ):
535 """Isole le solide de son arboresence
538 :solide: le solide à traiter
539 :n_recur: numéro de la récurrence
542 :objet: le solide isolé
543 :recover: la fonction de récupération
546 nom_fonction = __name__ + "/_isole_solide_a"
547 blabla = "Dans {} :".format(nom_fonction)
548 if self._verbose_max:
549 print_tab (n_recur, blabla)
550 texte = "Pour le solide '{}' ".format(solide.name())
551 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
552 print_tab (n_recur, texte)
554 if self._verbose_max:
555 print_tab (n_recur, ". Extraction du solide '{}'".format(self.objet_principal.name()))
557 # 1. Extraction du solide
558 remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
559 remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
561 self.nom_solide_aux = "{}_S".format(solide.name())
562 if self._verbose_max:
563 print_tab (n_recur, "\tAttribution à remove_subshapes.result() du nom '{}'".format(self.nom_solide_aux))
564 remove_subshapes.result().setName(self.nom_solide_aux)
566 self.fonction_0 = remove_subshapes
568 # 2. Récupération de l'objet principal
569 recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
570 if self._verbose_max:
571 print_tab (n_recur, "\tAttribution à recover du nom '{}'".format(self.objet_principal.name()))
572 recover.result().setName(self.objet_principal.name())
574 return remove_subshapes.result(), recover
576 #=========================== Fin de la méthode ==================================
578 #=========================== Début de la méthode =================================
580 def _isole_solide_b ( self, solide, n_recur ):
581 """Isole le solide de son arboresence
584 :solide: le solide à traiter
585 :n_recur: numéro de la récurrence
588 :objet: le solide isolé
589 :recover: la fonction de récupération
592 nom_fonction = __name__ + "/_isole_solide_b"
593 blabla = "Dans {} :".format(nom_fonction)
594 if self._verbose_max:
595 print_tab (n_recur, blabla)
596 texte = "Pour le solide '{}' ".format(solide.name())
597 texte += "de l'objet principal '{}'".format(self.objet_principal.name())
598 print_tab (n_recur, texte)
600 if self._verbose_max:
601 print_tab (n_recur, ". Mise en place du solide")
603 self.nom_solide_aux = self.objet_principal.name()
604 self.fonction_0 = None
608 #=========================== Fin de la méthode ==================================
610 #=========================== Début de la méthode =================================
612 def _faces_du_solide ( self, solide, n_recur=0 ):
613 """Détermine les faces d'un solide
616 :solide: solide SHAPER à traiter
617 :n_recur: niveau de récursivité
620 :l_faces_car: pour chaque face du solide (surface,caractéristiques)
623 nom_fonction = __name__ + "/_faces_du_solide"
624 blabla = "Dans {} :".format(nom_fonction)
625 if self._verbose_max:
626 print_tab (n_recur, blabla, saut_av=True)
630 if self._verbose_max:
631 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
632 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
635 #print_tab (n_recur, "volume = ", GeomAlgoAPI_ShapeTools.volume(solide.shape()))
636 # 1. Repérage des faces
637 objResult = solide.resultSubShapePair()[0]
639 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
641 l_faces.append(exp.current().face())
646 for iface, face in enumerate(l_faces):
647 surf = GeomAlgoAPI_ShapeTools.area(face)
648 caract = geom.shapeInfo(face)
649 if self._verbose_max:
650 print_tab (n_recur, "\tFace n°{} ; ".format(iface), "surface = {}, caractéristiques = {}".format(surf,caract))
651 l_faces_car.append((surf,caract))
655 #=========================== Fin de la méthode ==================================
657 #=========================== Début de la méthode =================================
659 def _calcul_caract_faces ( self, solide, n_recur ):
660 """Calcule les caractéristiques géométriques des faces du solide
663 :solide: solide SHAPER à traiter
664 :n_recur: niveau de récursivité
667 :tb_caract: tableau des caractéristiques géométriques des faces
670 nom_fonction = __name__ + "/_calcul_caract_faces"
671 blabla = "Dans {} :".format(nom_fonction)
672 if self._verbose_max:
673 print_tab (n_recur, blabla, saut_av=True)
674 print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
675 print_tab (n_recur, ".. shapeType : ", solide.shapeType())
677 # 1. Repérage des faces
678 objResult = solide.resultSubShapePair()[0]
680 exp = GeomAPI_ShapeExplorer(objResult.shape(), GeomAPI_Shape.FACE)
682 l_faces.append(exp.current().face())
685 # 2. Caractéristiques
686 nb_faces = len(l_faces)
687 tb_caract = np.zeros((nb_faces,3), dtype = 'object')
688 for iaux, face in enumerate(l_faces):
689 surf = GeomAlgoAPI_ShapeTools.area(face)
690 caract = geom.shapeInfo(face)
691 if self._verbose_max:
692 print_tab (n_recur, "\tFace n°{} ; ".format(iaux), "surface = {}, caractéristiques = {}".format(surf,caract))
694 tb_caract [iaux][0] = face
695 tb_caract [iaux][1] = surf
696 tb_caract [iaux][2] = caract
698 #if self._verbose_max:
699 #for iaux in range(nb_faces):
700 #print ("\t. tb_caract : {} {}".format(surf,tb_caract[iaux][2]))
704 #=========================== Fin de la méthode ==================================
706 #=========================== Début de la méthode =================================
708 def _tri_faces ( self, tb_caract, n_recur ):
709 """Trie les faces en fonction de leurs surfaces
712 :tb_caract: tableau des caractéristiques géométriques des faces
713 :n_recur: niveau de récursivité
716 :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
722 nom_fonction = __name__ + "/_tri_faces"
723 blabla = "Dans {} :".format(nom_fonction)
725 # Tri du tableau en fonction des surfaces
726 if self._verbose_max:
727 print_tab (n_recur, blabla)
728 print_tab (n_recur, "tb_caract brut : ", tb_caract)
729 tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
730 if self._verbose_max:
731 print_tab (n_recur, "tb_caract trié :", tb_caract_1)
733 if self._verbose_max:
734 texte = "\tSurface de la plus grande face : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
735 texte += "\tSurface de la face suivante : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
736 if self._verbose_max:
737 texte += "\n\tSurface de la 3ème face suivante : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
740 # La surface suivante doit être différente, sinon ce n'est pas un solide mince
741 ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
742 if ( ecart < self._epsilon ):
743 message = "\nSolide '{}'\n".format(self.nom_solide)
744 message += ". Surface de la plus grande face : {}\n".format(tb_caract_1[-1][1])
745 message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
746 message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
747 if self._verbose_max:
748 message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
749 message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
750 message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
752 self.d_statut_so[self.nom_solide] = -1
753 self.faces_pb_nb += 1
754 self.faces_pb_msg += message
756 return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
758 #=========================== Fin de la méthode ==================================
760 #=========================== Début de la méthode =================================
762 def _verif_epaisseur ( self, epaisseur ):
763 """Contrôle de la validité de l'épaisseur
766 :epaisseur: épaisseur du solide
769 nom_fonction = __name__ + "/_verif_epaisseur"
770 blabla = "Dans {} :\n".format(nom_fonction)
772 if self._verbose_max:
774 texte += ". Epaisseur du solide : {}\n".format(epaisseur)
775 texte += ". EP_MIN : {}".format(EP_MIN)
778 if ( epaisseur <= EP_MIN ):
779 message = "\nSolide '{}'\n".format(self.nom_solide)
780 message += ". Epaisseur : {}\n".format(epaisseur)
781 message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
782 message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
784 self.d_statut_so[self.nom_solide] = 2
785 self.faces_pb_nb += 1
786 self.faces_pb_msg += message
790 #print ("erreur = {}".format(erreur))
794 #=========================== Fin de la méthode ==================================
796 #=========================== Début de la méthode =================================
798 def _cree_face_mediane ( self, solide, caract_face_1, caract_face_2, n_recur ):
799 """Crée la face médiane entre deux autres
802 :solide: solide SHAPER à traiter
803 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
804 :n_recur: niveau de récursivité
807 :face: la face médiane créée
810 nom_fonction = __name__ + "/_cree_face_mediane"
811 blabla = "Dans {} :".format(nom_fonction)
813 if self._verbose_max:
814 print_tab (n_recur, blabla)
815 print_tab (n_recur, "face_1 : " ,caract_face_1)
816 print_tab (n_recur, "face_2 : " ,caract_face_2)
821 # 1. Forme de la face
822 forme = caract_face_1[2][0]
823 if self._verbose_max:
824 print_tab (n_recur, "forme = {}".format(forme) )
826 # 2. Traitement selon la forme de la face
828 if forme in ( "Disk" , "Plane", "Rectangle"):
829 erreur, face = self._cree_face_mediane_plane ( solide, caract_face_1, caract_face_2, n_recur )
831 # 2.2. Face cylindrique
832 elif ( forme == "Cylinder" ):
833 erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
835 # 2.3. Face sphérique
836 elif ( forme == "Sphere" ):
837 erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
840 elif ( forme == "Torus" ):
841 erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
844 elif ( forme == "Cone" ):
845 erreur, face = self._cree_face_mediane_cone ( caract_face_1, caract_face_2, n_recur )
847 # 2.N. Face de forme inconnue
849 message = "\nSolide '{}'\n".format(self.nom_solide)
850 message += "sa face la plus grande est de forme : {}\n".format(forme)
851 message += "==> Impossible de créer la face médiane.\n"
853 self.d_statut_so[self.nom_solide] = -2
854 self.faces_pb_nb += 1
855 self.faces_pb_msg += message
857 # 3. Gestion de la face produite
860 self._cree_face_mediane_0 ( face, n_recur )
864 #=========================== Fin de la méthode ==================================
866 #=========================== Début de la méthode =================================
868 def _cree_face_mediane_0 ( self, face, n_recur ):
869 """Gestion de la face médiane créée entre deux autres
872 :face: la face médiane créée
873 :n_recur: niveau de récursivité
876 nom_fonction = __name__ + "/_cree_face_mediane_0"
877 blabla = "Dans {} :".format(nom_fonction)
879 if self._verbose_max:
880 print_tab (n_recur, blabla)
883 nom_face = self.nom_solide+"_M"
884 if self._verbose_max:
885 print_tab (n_recur,"Nom de la face créée : ", nom_face)
886 #if ( self.nom_solide_aux != self.objet_principal.name() ):
888 nommage (face, nom_face)
890 # 2. Mémorisation de la face et de la fonction initiale
891 self.l_faces_m.append((face, self.fonction_0))
893 # 3. Couleur verte pour la face
894 self._couleur_objet (face, coul_r=0, coul_g=170, coul_b=0)
896 # 4. Changement de statut pour le solide
897 self.d_statut_so[self.nom_solide] = 1
901 #=========================== Fin de la méthode ==================================
903 #=========================== Début de la méthode =================================
905 def _cree_face_mediane_plane ( self, solide, caract_face_1, caract_face_2, n_recur ):
906 """Crée la face médiane entre deux autres - cas des surfaces planes
909 :solide: l'objet solide à traiter
910 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
911 :n_recur: niveau de récursivité
914 :face: la face médiane
917 nom_fonction = __name__ + "/_cree_face_mediane_plane"
918 blabla = "Dans {} :".format(nom_fonction)
919 if self._verbose_max:
920 print_tab (n_recur, blabla)
922 # Caractéristiques des surfaces
923 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 )
925 # Contrôle de la validité de l'épaisseur
926 erreur = self._verif_epaisseur ( d_face_1_2 )
928 # Création de la face
930 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 )
936 #=========================== Fin de la méthode ==================================
938 #=========================== Début de la méthode =================================
940 def _cree_face_mediane_plane_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
941 """Crée la face médiane entre deux autres - cas des surfaces planes
943 Décodage des caractéristiques
946 :solide: l'objet solide à traiter
947 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
948 :n_recur: niveau de récursivité
951 :coo_x, coo_y, coo_z: coordonnées du centre de la base
952 :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
953 :taille: estimation de la taille de la future face
954 :d_face_1_2: la distance entre les deux faces
957 nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
958 blabla = "Dans {} :".format(nom_fonction)
960 if self._verbose_max:
961 print_tab (n_recur, blabla)
962 print_tab (n_recur, "caract_face_1 : ", caract_face_1)
963 print_tab (n_recur, "caract_face_2 : ", caract_face_2)
965 # 1. Caractéristiques de la base
966 # Coordonnées du centre de la base
967 coo_x = caract_face_1[2][1]
968 coo_y = caract_face_1[2][2]
969 coo_z = caract_face_1[2][3]
970 # Coordonnées du vecteur normal
971 vnor_x = caract_face_1[2][4]
972 vnor_y = caract_face_1[2][5]
973 vnor_z = caract_face_1[2][6]
974 # taille : la diagonale de la boîte englobante permet d'être certain de tout prendre
975 l_diag = self._calcul_boite_englobante ( solide, n_recur )
977 if self._verbose_max:
978 print_tab (n_recur, "Taille englobante : ",taille)
980 # 2. Distance entre les deux faces
981 face_1 = caract_face_1[0]
982 face_2 = caract_face_2[0]
983 d_face_1_2 = GeomAlgoAPI_ShapeTools.minimalDistance(face_1, face_2)
984 if self._verbose_max:
985 print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
987 return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
989 #=========================== Fin de la méthode ==================================
991 #=========================== Début de la méthode =================================
993 def _cree_face_mediane_plane_1 ( self, solide, coo_c, vnor, taille, d_face_1_2, n_recur ):
994 """Crée la face médiane entre deux autres - cas des surfaces planes
996 Création des objets temporaires et de la face médiane
999 :solide: l'objet solide à traiter
1000 :coo_c: coordonnées du centre de la base
1001 :vnor: coordonnées du vecteur normal
1002 :taille: estimation de la taille de la future face
1003 :d_face_1_2: la distance entre les deux faces
1004 :n_recur: niveau de récursivité
1007 :face: la face médiane
1010 nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
1011 blabla = "Dans {} :".format(nom_fonction)
1012 if self._verbose_max:
1013 print_tab (n_recur, blabla)
1014 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1015 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
1016 print_tab (n_recur, "Taille : ", taille)
1017 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1019 # 1. Objets préalables
1020 nom_par_1 = "{}_taille".format(self.nom_solide)
1021 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(taille))
1023 centre, v_norm, plan = self._cree_centre_axe_plan ( coo_c, vnor, self.nom_solide, n_recur )
1025 # 2. Création de l'esquisse
1026 sketch = self._cree_face_mediane_plane_1_a ( plan, centre, nom_par_1, taille, n_recur )
1029 face = self._cree_face_mediane_plane_1_b ( solide, sketch, v_norm, d_face_1_2, n_recur )
1031 #print ("fin de {}".format(nom_fonction))
1035 #=========================== Fin de la méthode ==================================
1037 #=========================== Début de la méthode =================================
1039 def _cree_face_mediane_plane_1_a ( self, plan, centre, nom_par_1, taille, n_recur ):
1040 """Crée la face médiane entre deux autres - cas des surfaces planes - l'esquisse
1045 :nom_par_1: nom du paramètre
1046 :taille: estimation de la taille de la future face
1047 :n_recur: niveau de récursivité
1053 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_a"
1054 blabla = "Dans {} :".format(nom_fonction)
1055 if self._verbose_max:
1056 print_tab (n_recur, blabla)
1057 print_tab (n_recur, "Plan : {}".format(plan.name()))
1058 print_tab (n_recur, "Centre : {}".format(centre.name()))
1059 print_tab (n_recur, "Paramètre : {}".format(nom_par_1))
1060 print_tab (n_recur, "taille : {}".format(taille))
1062 sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1064 ### Create SketchLine
1065 SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1066 sketch.setHorizontal(SketchLine_1.result())
1068 ### Create SketchLine
1069 SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1070 sketch.setVertical(SketchLine_2.result())
1071 sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
1073 ### Create SketchLine
1074 SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1075 sketch.setHorizontal(SketchLine_3.result())
1076 sketch.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
1077 sketch.setLength(SketchLine_3.result(), nom_par_1)
1079 ### Create SketchLine
1080 SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1081 sketch.setVertical(SketchLine_4.result())
1082 sketch.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
1083 sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
1084 sketch.setEqual(SketchLine_3.result(), SketchLine_4.result())
1086 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", centre.name()), False)
1087 SketchPoint_1 = SketchProjection_1.createdFeature()
1089 ### Create SketchLine
1090 SketchLine_5 = sketch.addLine(-taille/2., taille/2., taille/2., -taille/2.)
1091 SketchLine_5.setAuxiliary(True)
1092 sketch.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
1093 sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_5.endPoint())
1094 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_5.result())
1096 ### Create SketchLine
1097 SketchLine_6 = sketch.addLine(taille/2., taille/2., -taille/2., -taille/2.)
1098 SketchLine_6.setAuxiliary(True)
1099 sketch.setCoincident(SketchLine_2.startPoint(), SketchLine_6.startPoint())
1100 sketch.setCoincident(SketchLine_4.startPoint(), SketchLine_6.endPoint())
1101 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_6.result())
1105 nom_sketch = "{}_esquisse".format(self.nom_solide)
1106 nommage (sketch, nom_sketch)
1108 #print ("fin de {}".format(nom_fonction))
1112 #=========================== Fin de la méthode ==================================
1114 #=========================== Début de la méthode =================================
1116 def _cree_face_mediane_plane_1_b ( self, solide, sketch, v_norm, d_face_1_2, n_recur ):
1117 """Crée la face médiane entre deux autres - cas des surfaces planes
1119 Création de la face médiane
1122 :solide: l'objet solide à traiter
1124 :v_norm: vecteur normal
1125 :d_face_1_2: la distance entre les deux faces
1126 :n_recur: niveau de récursivité
1129 :face: la face médiane
1132 nom_fonction = __name__ + "/_cree_face_mediane_plane_1_b"
1133 blabla = "Dans {} :".format(nom_fonction)
1134 if self._verbose_max:
1135 print_tab (n_recur, blabla)
1136 print_tab (n_recur, "Esquisse : ", sketch.name())
1137 print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1139 ### Create LinearCopy
1140 LinearCopy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1141 nom = "{}_0".format(self.nom_solide_aux)
1142 nommage (LinearCopy_1, nom)
1145 Recover_1 = model.addRecover(self.part_doc, LinearCopy_1, [solide])
1146 nom = "{}_1".format(self.nom_solide_aux)
1147 nommage (Recover_1, nom)
1149 # Création d'une face ; on la translate d'une demi-épaisseur.
1150 for iaux in range(2):
1152 distance = -0.5*d_face_1_2*float(2*iaux-1)
1153 nom_solide = "{}_{}".format(self.nom_solide_aux,iaux)
1154 face = self._cree_face_mediane_plane_2 ( sketch.name(), v_norm.name(), nom_solide, distance, iaux, n_recur )
1157 face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1159 # Si l'intersection est vide, on la translate dans l'autre sens
1161 if self._verbose_max:
1162 print_tab (n_recur, "L'intersection est vide.")
1165 #print ("fin de {}".format(nom_fonction))
1169 #=========================== Fin de la méthode ==================================
1171 #=========================== Début de la méthode =================================
1173 def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1174 """Crée la face médiane entre deux autres - cas des surfaces planes
1176 Création des objets temporaires et de la face médiane
1179 :face: la face médiane
1180 :Recover_1: la récupératiuon du solide
1181 :n_recur: niveau de récursivité
1184 :face: la face médiane
1187 nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1188 blabla = "Dans {} :".format(nom_fonction)
1189 if self._verbose_max:
1190 print_tab (n_recur, blabla)
1191 print_tab (n_recur, "face : ", face.name())
1193 # Si on traite un objet solide unique, on le récupère
1194 if ( self.nom_solide_aux == self.objet_principal.name() ):
1195 if self._verbose_max:
1196 print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1197 Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1198 Recover_2.result().setName("{}_S".format(self.nom_solide_aux))
1200 nb_inter = face.result().numberOfSubs()
1201 if self._verbose_max:
1202 print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1205 face = self._cree_face_mediane_plane_3 ( face )
1209 #=========================== Fin de la méthode ==================================
1211 #=========================== Début de la méthode =================================
1213 def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, distance, icpt, n_recur ):
1214 """Crée la face médiane entre deux autres - cas des surfaces planes
1216 Intersection de la face avec le solide
1219 :nom_sketch: nom de l'esquisse
1220 :nom_normal: nom du vecteur normal
1221 :nom_solide: nom du solide à intersecter
1222 :distance: la distance de translation
1223 :icpt: numéro de la tentative
1226 :face: la face médiane
1229 nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1230 blabla = "Dans {} :\n".format(nom_fonction)
1231 if self._verbose_max:
1232 print_tab (n_recur, blabla)
1233 print_tab (n_recur, "nom_sketch : ", nom_sketch)
1234 print_tab (n_recur, "nom_normal : ", nom_normal)
1235 print_tab (n_recur, "nom_solide : ", nom_solide)
1236 print_tab (n_recur, "distance : ", distance)
1238 # Création d'une face
1239 Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1240 nom_face_1 = "{}_face_1_{}".format(self.nom_solide_aux,icpt)
1241 nommage (Face_1, nom_face_1)
1244 Translation_1 = model.addTranslation(self.part_doc, [model.selection("FACE", nom_face_1)], axis = model.selection("EDGE", nom_normal), distance = distance, keepSubResults = True)
1245 nom_trans = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1246 nommage (Translation_1, nom_trans)
1247 Translation_1.result().setColor(85, 0, 255)
1249 # Intersection de cette face avec le solide initial
1250 face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_trans)], keepSubResults = True)
1254 #=========================== Fin de la méthode ==================================
1256 #=========================== Début de la méthode =================================
1258 def _cree_face_mediane_plane_3 ( self, face ):
1259 """Crée la face médiane entre deux autres - cas des surfaces planes
1261 Fusion des 2 intersections
1264 :face: la face médiane composée de plusieurs intersections
1267 :face_m: la face médiane
1270 nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1271 blabla = "Dans {} :\n".format(nom_fonction)
1272 if self._verbose_max:
1276 # Nommage des sous-objets
1278 for iaux in range(face.result().numberOfSubs()):
1279 nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1280 face.result().subResult(iaux).setName(nom)
1281 l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1284 if self._verbose_max:
1285 print ("Fusion de {} faces.".format(len(l_fuse)))
1286 face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1290 #=========================== Fin de la méthode ==================================
1292 #=========================== Début de la méthode =================================
1294 def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1295 """Crée la face médiane entre deux autres - cas des cylindres
1298 :solide: solide SHAPER à traiter
1299 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1300 :n_recur: niveau de récursivité
1303 :face: la face médiane
1306 nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1307 blabla = "Dans {} :".format(nom_fonction)
1310 if self._verbose_max:
1311 print_tab (n_recur, blabla)
1312 print_tab (n_recur, "face_1 : ", caract_face_1)
1313 print_tab (n_recur, "face_2 : ", caract_face_2)
1315 # Caractéristiques des cylindres
1316 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 )
1318 # Contrôle de la validité de l'épaisseur
1319 erreur = self._verif_epaisseur ( epaisseur )
1321 # Création de la face
1323 face = self._cree_face_mediane_cylindre_1 ( (coo_x, coo_y, coo_z), (axe_x, axe_y, axe_z), rayon, hauteur, n_recur )
1325 self._couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255)
1330 #=========================== Fin de la méthode ==================================
1332 #=========================== Début de la méthode =================================
1334 def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1335 """Crée la face médiane entre deux autres - cas des cylindres
1337 Décodage des caractéristiques
1340 :solide: l'objet solide à traiter
1341 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1342 :n_recur: niveau de récursivité
1345 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1346 :axe_x, axe_y, axe_z: coordonnées de l'axe
1347 :rayon: rayon moyen entre les deux faces
1348 :hauteur: hauteur du cylindre
1349 :epaisseur: épaisseur de l'interface entre les deux faces
1352 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1353 blabla = "Dans {} :".format(nom_fonction)
1355 if self._verbose_max:
1356 print_tab (n_recur, blabla)
1357 print_tab (n_recur, "face_1 : ", caract_face_1)
1358 print_tab (n_recur, "face_2 : ", caract_face_2)
1360 # Coordonnées du centre de la base
1361 coo_x = caract_face_1[2][1]
1362 coo_y = caract_face_1[2][2]
1363 coo_z = caract_face_1[2][3]
1364 # Coordonnées de l'axe
1365 axe_x = caract_face_1[2][4]
1366 axe_y = caract_face_1[2][5]
1367 axe_z = caract_face_1[2][6]
1369 rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1370 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1371 l_diag = self._calcul_boite_englobante ( solide, n_recur )
1372 hauteur = 10.*l_diag
1373 if self._verbose_max:
1374 print_tab (n_recur, "Hauteur englobante : ", hauteur)
1376 epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1378 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1380 #=========================== Fin de la méthode ==================================
1382 #=========================== Début de la méthode =================================
1384 def _cree_face_mediane_cylindre_1 ( self, coo_c, v_axe, rayon, hauteur, n_recur ):
1385 """Crée la face médiane entre deux autres - cas des cylindres
1387 Création des objets temporaires et de la face externe du cylindre support
1390 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1391 :axe_x, axe_y, axe_z: coordonnées de l'axe
1392 :rayon: rayon moyen entre les deux faces
1393 :hauteur: hauteur du cylindre
1394 :n_recur: niveau de récursivité
1397 :face: la face médiane
1399 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1400 blabla = "Dans {} :\n".format(nom_fonction)
1402 # Les caractéristiques du cylindre à créer
1403 if self._verbose_max:
1404 print_tab (n_recur, blabla)
1405 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1406 print_tab (n_recur, "Axe : ({}, {}, {})".format(v_axe[0], v_axe[1], v_axe[2]))
1407 print_tab (n_recur, "Rayon : ", rayon)
1408 print_tab (n_recur, "Hauteur : ", hauteur)
1410 # 1. Objets préalables
1411 nom_par_1 = "{}_R".format(self.nom_solide)
1412 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1413 nom_par_2 = "{}_H".format(self.nom_solide)
1414 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(hauteur))
1416 centre, _, plan = self._cree_centre_axe_plan ( coo_c, v_axe, self.nom_solide, n_recur )
1418 # 2. Création de l'esquisse
1419 sketch = self._cree_face_mediane_cylindre_1_a ( plan, centre, rayon, nom_par_1, n_recur )
1422 face = self._cree_face_mediane_cylindre_1_b ( sketch, nom_par_2, n_recur )
1426 #=========================== Fin de la méthode ==================================
1428 #=========================== Début de la méthode =================================
1430 def _cree_face_mediane_cylindre_1_a ( self, plan, centre, rayon, nom_par_1, n_recur ):
1431 """Crée la face médiane entre deux autres - cas des cylindres
1433 Création des objets temporaires et de la face externe du cylindre support
1436 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1437 :axe_x, axe_y, axe_z: coordonnées de l'axe
1438 :rayon: rayon moyen entre les deux faces
1439 :nom_par_1: nom_par_1
1440 :n_recur: niveau de récursivité
1443 :face: la face médiane
1445 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1_a"
1446 blabla = "Dans {} :\n".format(nom_fonction)
1448 # Les caractéristiques du cylindre à créer
1449 if self._verbose_max:
1450 print_tab (n_recur, blabla)
1451 print_tab (n_recur, "Plan : {}".format(plan.name()))
1452 print_tab (n_recur, "Centre : {}".format(centre.name()))
1453 print_tab (n_recur, "Rayon : ", rayon)
1455 sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1457 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", centre.name()), False)
1458 SketchPoint_1 = SketchProjection_1.createdFeature()
1460 SketchCircle_1 = sketch.addCircle(0., 0., rayon)
1461 sketch.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
1462 sketch.setRadius(SketchCircle_1.results()[1], nom_par_1)
1465 nom_sketch = "{}_esquisse".format(self.nom_solide)
1466 nommage (sketch, nom_sketch)
1470 #=========================== Fin de la méthode ==================================
1472 #=========================== Début de la méthode =================================
1474 def _cree_face_mediane_cylindre_1_b ( self, sketch, nom_par_2, n_recur ):
1475 """Crée la face médiane entre deux autres - cas des cylindres
1477 Création des objets temporaires et de la face externe du cylindre support
1481 :n_recur: niveau de récursivité
1484 :face: la face médiane
1486 nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1_b"
1487 blabla = "Dans {} :\n".format(nom_fonction)
1489 # Les caractéristiques du cylindre à créer
1490 if self._verbose_max:
1491 print_tab (n_recur, blabla)
1492 print_tab (n_recur, "Esquisse : ", sketch.name())
1493 print_tab (n_recur, "nom_par_2 : ", nom_par_2)
1495 # Création du cylindre complet
1496 cylindre = model.addExtrusion(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(sketch.name()))], model.selection(), nom_par_2, nom_par_2, "Edges")
1498 nom_cylindre = "{}_cylindre".format(self.nom_solide)
1499 nommage (cylindre, nom_cylindre, (85, 0, 255))
1501 # Intersection de la face cylindrique avec le solide initial
1502 face = self._creation_face_inter ( nom_cylindre )
1506 #=========================== Fin de la méthode ==================================
1508 #=========================== Début de la méthode =================================
1510 def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1511 """Crée la face médiane entre deux autres - cas des sphères
1514 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1515 :n_recur: niveau de récursivité
1518 :face: la face médiane
1521 nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1522 blabla = "Dans {} :".format(nom_fonction)
1525 if self._verbose_max:
1526 print_tab (n_recur, blabla)
1527 print_tab (n_recur, "face_1 : ", caract_face_1)
1528 print_tab (n_recur, "face_2 : ", caract_face_2)
1530 # Caractéristiques des sphères
1531 coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1533 # Contrôle de la validité de l'épaisseur
1534 erreur = self._verif_epaisseur ( epaisseur )
1536 # Création de la face
1538 face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1544 #=========================== Fin de la méthode ==================================
1546 #=========================== Début de la méthode =================================
1548 def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1549 """Crée la face médiane entre deux autres - cas des sphères
1551 Décodage des caractéristiques
1554 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1555 :n_recur: niveau de récursivité
1558 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1559 :rayon: rayon moyen entre les deux faces
1560 :epaisseur: épaisseur de l'interface entre les deux faces
1563 nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1564 blabla = "Dans {} :".format(nom_fonction)
1567 if self._verbose_max:
1568 print_tab (n_recur, blabla)
1569 print_tab (n_recur, "face_1 : ", caract_face_1)
1570 print_tab (n_recur, "face_2 : ", caract_face_2)
1572 # Coordonnées du centre de la sphère
1573 coo_x = caract_face_1[2][1]
1574 coo_y = caract_face_1[2][2]
1575 coo_z = caract_face_1[2][3]
1577 rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1579 epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1581 return coo_x, coo_y, coo_z, rayon, epaisseur
1583 #=========================== Fin de la méthode ==================================
1585 #=========================== Début de la méthode =================================
1587 def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1588 """Crée la face médiane entre deux autres - cas des sphères
1590 Création des objets temporaires et de la face externe de la sphère support
1593 :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1594 :rayon: rayon moyen entre les deux faces
1597 :face: la face externe de la sphère support
1600 nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1601 blabla = "Dans {} :\n".format(nom_fonction)
1603 # Les caractéristiques de la sphère à créer
1604 if self._verbose_max:
1606 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1607 texte += "Rayon : {}".format(rayon)
1610 # Création du point central
1611 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1612 nom_centre = "{}_centre".format(self.nom_solide)
1613 centre.result().setName(nom_centre)
1615 # Création d'un plan passant par ce centre et cet axe
1616 plan = model.addPlane(self.part_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", nom_centre), False)
1617 nom_plan = "{}_plan".format(self.nom_solide)
1618 plan.result().setName(nom_plan)
1620 # Création de l'esquisse
1621 nom_par_1 = "{}_R".format(self.nom_solide)
1622 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1624 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1626 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1627 SketchPoint_1 = SketchProjection_1.createdFeature()
1629 ### Create SketchArc
1630 SketchArc_1 = sketch.addArc(coo_x, coo_y, coo_x-rayon, coo_y, coo_x+rayon, coo_y, False)
1631 sketch.setRadius(SketchArc_1.results()[1], nom_par_1)
1632 sketch.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
1634 ### Create SketchLine
1635 SketchLine_1 = sketch.addLine(coo_x-rayon, coo_y, coo_x+rayon, coo_y)
1636 nom_ligne = "{}_ligne".format(self.nom_solide)
1637 SketchLine_1.setName(nom_ligne)
1638 SketchLine_1.result().setName(nom_ligne)
1639 SketchLine_1.setAuxiliary(True)
1640 sketch.setHorizontal(SketchLine_1.result())
1641 sketch.setCoincident(SketchArc_1.startPoint(), SketchLine_1.startPoint())
1642 sketch.setCoincident(SketchArc_1.endPoint(), SketchLine_1.endPoint())
1643 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result())
1646 nom_sketch = "{}_esquisse".format(self.nom_solide)
1647 sketch.setName(nom_sketch)
1648 sketch.result().setName(nom_sketch)
1650 # Création de la sphère complète
1651 sphere = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", "{}/{}".format(nom_sketch,nom_ligne)), 360, 0, "Edges")
1653 nom_sphere = "{}_sphere".format(self.nom_solide)
1654 nommage (sphere, nom_sphere, (85, 0, 255))
1656 # Intersection de la face sphérique avec le solide initial
1657 face = self._creation_face_inter ( nom_sphere )
1661 #=========================== Fin de la méthode ==================================
1663 #=========================== Début de la méthode =================================
1665 def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1666 """Crée la face médiane entre deux autres - cas des tores
1669 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1670 :n_recur: niveau de récursivité
1673 :face: la face médiane
1676 nom_fonction = __name__ + "/_cree_face_mediane_tore"
1677 blabla = "Dans {} :".format(nom_fonction)
1680 if self._verbose_max:
1681 print_tab (n_recur, blabla)
1682 print_tab (n_recur, "face_1 : ", caract_face_1)
1683 print_tab (n_recur, "face_2 : ", caract_face_2)
1685 # Caractéristiques des tores
1686 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 )
1688 # Contrôle de la validité de l'épaisseur (bidon)
1689 erreur = self._verif_epaisseur ( EP_MIN*10. )
1691 # Création de la face
1693 face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1699 #=========================== Fin de la méthode ==================================
1701 #=========================== Début de la méthode =================================
1703 def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1704 """Crée la face médiane entre deux autres - cas des tores
1706 Décodage des caractéristiques
1709 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1710 :n_recur: niveau de récursivité
1713 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1714 :axe_x, axe_y, axe_z: coordonnées de l'axe
1715 :rayon_1 : rayon principal
1716 :rayon_2 : rayon secondaire
1719 nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1720 blabla = "Dans {} :".format(nom_fonction)
1723 if self._verbose_max:
1724 print_tab (n_recur, blabla)
1725 print_tab (n_recur, "face_1 : ", caract_face_1)
1726 print_tab (n_recur, "face_2 : ", caract_face_2)
1728 # Coordonnées du centre du tore
1729 coo_x = caract_face_1[2][1]
1730 coo_y = caract_face_1[2][2]
1731 coo_z = caract_face_1[2][3]
1732 # Coordonnées de l'axe
1733 axe_x = caract_face_1[2][4]
1734 axe_y = caract_face_1[2][5]
1735 axe_z = caract_face_1[2][6]
1737 rayon_1 = caract_face_2[2][7]
1738 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1740 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1742 #=========================== Fin de la méthode ==================================
1744 #=========================== Début de la méthode =================================
1746 def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1747 """Crée la face médiane entre deux autres - cas des tores
1749 Création des objets temporaires et de la face externe du tore support
1752 :coo_x, coo_y, coo_z: coordonnées du centre du tore
1753 :axe_x, axe_y, axe_z: coordonnées de l'axe
1754 :rayon_1 : rayon principal
1755 :rayon_2 : rayon secondaire
1758 :face: la face externe du tore support
1761 nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1762 blabla = "Dans {} :\n".format(nom_fonction)
1765 if self._verbose_max:
1767 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1768 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1769 texte += "Rayon principal : {}\n".format(rayon_1)
1770 texte += "Rayon secondaire : {}".format(rayon_2)
1773 # Création du point central
1774 centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1775 nom_centre = "{}_centre".format(self.nom_solide)
1776 centre.result().setName(nom_centre)
1779 axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1780 nom_axe = "{}_axe".format(self.nom_solide)
1781 axe.result().setName(nom_axe)
1783 # Création d'un plan passant par ce centre et cet axe
1784 plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1785 nom_plan = "{}_plan".format(self.nom_solide)
1786 plan.result().setName(nom_plan)
1788 # Création de l'esquisse
1789 nom_par_1 = "{}_R_1".format(self.nom_solide)
1790 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1791 nom_par_2 = "{}_R_2".format(self.nom_solide)
1792 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1794 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1796 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1797 SketchPoint_1 = SketchProjection_1.createdFeature()
1799 SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1800 SketchLine_1 = SketchProjection_2.createdFeature()
1802 SketchPoint_2 = sketch.addPoint(rayon_1, 0.)
1803 sketch.setDistance(SketchPoint_1.result(), SketchPoint_2.coordinates(), nom_par_1, True)
1805 SketchLine_2 = sketch.addLine(0., 0., rayon_1, 0.)
1806 SketchLine_2.setAuxiliary(True)
1807 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1808 sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_2.endPoint())
1809 sketch.setPerpendicular(SketchLine_1.result(), SketchLine_2.result())
1811 SketchCircle_1 = sketch.addCircle(0., 0., rayon_2)
1812 sketch.setCoincident(SketchPoint_2.result(), SketchCircle_1.center())
1813 sketch.setRadius(SketchCircle_1.results()[1], nom_par_2)
1816 nom_sketch = "{}_esquisse".format(self.nom_solide)
1817 sketch.setName(nom_sketch)
1818 sketch.result().setName(nom_sketch)
1820 # Création du tore complet
1821 nom_tore = "{}_tore".format(self.nom_solide)
1822 self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_tore )
1824 # Intersection de la face torique avec le solide initial
1825 face = self._creation_face_inter ( nom_tore )
1829 #=========================== Fin de la méthode ==================================
1831 #=========================== Début de la méthode =================================
1833 def _cree_face_mediane_cone ( self, caract_face_1, caract_face_2, n_recur ):
1834 """Crée la face médiane entre deux autres - cas des cones
1837 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1838 :n_recur: niveau de récursivité
1841 :face: la face médiane
1844 nom_fonction = __name__ + "/_cree_face_mediane_cone"
1845 blabla = "Dans {} :".format(nom_fonction)
1848 if self._verbose_max:
1849 print_tab (n_recur, blabla)
1850 print_tab (n_recur, "face_1 : ", caract_face_1)
1851 print_tab (n_recur, "face_2 : ", caract_face_2)
1853 # Caractéristiques des cones
1854 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 )
1856 # Contrôle de la validité de l'épaisseur (bidon)
1857 erreur = self._verif_epaisseur ( EP_MIN*10. )
1859 # Création de la face
1861 face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1867 #=========================== Fin de la méthode ==================================
1869 #=========================== Début de la méthode =================================
1871 def _cree_face_mediane_cone_0 ( self, caract_face_1, caract_face_2, n_recur ):
1872 """Crée la face médiane entre deux autres - cas des cones
1874 Décodage des caractéristiques
1877 :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1878 :n_recur: niveau de récursivité
1881 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1882 :axe_x, axe_y, axe_z: coordonnées de l'axe
1883 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1884 :hauteur: hauteur du cone
1887 nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1888 blabla = "Dans {} :".format(nom_fonction)
1891 if self._verbose_max:
1892 print_tab (n_recur, blabla)
1893 print_tab (n_recur, "face_1 : ", caract_face_1)
1894 print_tab (n_recur, "face_2 : ", caract_face_2)
1896 # Coordonnées du centre de la base
1897 coo_x = caract_face_1[2][1]
1898 coo_y = caract_face_1[2][2]
1899 coo_z = caract_face_1[2][3]
1900 # Coordonnées de l'axe
1901 axe_x = caract_face_1[2][4]
1902 axe_y = caract_face_1[2][5]
1903 axe_z = caract_face_1[2][6]
1905 rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1906 rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1908 hauteur = caract_face_1[2][9]
1911 if self._verbose_max:
1912 print_tab (n_recur, "coo_x : ", coo_x)
1913 print_tab (n_recur, "coo_y : ", coo_y)
1914 print_tab (n_recur, "coo_z : ", coo_z)
1915 print_tab (n_recur, "axe_x : ", axe_x)
1916 print_tab (n_recur, "axe_y : ", axe_y)
1917 print_tab (n_recur, "axe_z : ", axe_z)
1918 print_tab (n_recur, "rayon_1 : ", rayon_1)
1919 print_tab (n_recur, "rayon_2 : ", rayon_2)
1920 print_tab (n_recur, "hauteur : ", hauteur)
1922 return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1924 #=========================== Fin de la méthode ==================================
1926 #=========================== Début de la méthode =================================
1928 def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1929 """Crée la face médiane entre deux autres - cas des cones
1931 Création des objets temporaires et de la face externe du cone support
1934 :coo_x, coo_y, coo_z: coordonnées du centre de la base
1935 :axe_x, axe_y, axe_z: coordonnées de l'axe
1936 :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1937 :hauteur: hauteur du cone
1940 :face: la face externe du cone support
1942 nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1943 blabla = "Dans {} :\n".format(nom_fonction)
1946 if self._verbose_max:
1948 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1949 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1950 texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
1951 texte += "Hauteur : {}".format(hauteur)
1954 # 1. Création du point central de la base, côté rayon_1
1955 centre_1 = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1956 nom_centre_1 = "{}_centre_1".format(self.nom_solide)
1957 centre_1.result().setName(nom_centre_1)
1959 # 2. Création du point central, du côté de rayon_2
1960 centre_2 = model.addPoint(self.part_doc, coo_x+hauteur*axe_x, coo_y+hauteur*axe_y, coo_z+hauteur*axe_z)
1961 nom_centre_2 = "{}_centre_2".format(self.nom_solide)
1962 centre_2.result().setName(nom_centre_2)
1964 # 3. Création de l'axe
1965 axe = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre_1), model.selection("VERTEX", nom_centre_2))
1966 nom_axe = "{}_axe".format(self.nom_solide)
1967 axe.result().setName(nom_axe)
1969 # 4. Création d'un plan passant par le centre de la base et l'axe
1970 # 4.1. Création d'un vecteur perpendiculaire à l'axe
1972 v_perp = model.addAxis(self.part_doc, -coeff*axe_y, coeff*axe_x, 0.)
1973 nom_v_perp = "{}_v_perp".format(self.nom_solide)
1974 v_perp.result().setName(nom_v_perp)
1975 # 4.2. Création du plan
1976 plan = model.addPlane(self.part_doc, model.selection("EDGE",nom_v_perp), model.selection("VERTEX", nom_centre_1), True)
1977 nom_plan = "{}_plan".format(self.nom_solide)
1978 plan.result().setName(nom_plan)
1981 nom_par_1 = "{}_R_1".format(self.nom_solide)
1982 model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1983 nom_par_2 = "{}_R_2".format(self.nom_solide)
1984 model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1985 nom_par_3 = "{}_H".format(self.nom_solide)
1986 model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
1988 # 6. Création de l'esquisse
1990 sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1992 # 6.1. Projection des centres et de l'axe
1993 SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre_1), False)
1994 SketchPoint_1 = SketchProjection_1.createdFeature()
1995 sk_coo_x_1 = SketchAPI_Point(SketchPoint_1).coordinates().x()
1996 sk_coo_y_1 = SketchAPI_Point(SketchPoint_1).coordinates().y()
1998 SketchProjection_2 = sketch.addProjection(model.selection("VERTEX", nom_centre_2), False)
1999 SketchPoint_2 = SketchProjection_2.createdFeature()
2000 sk_coo_x_2 = SketchAPI_Point(SketchPoint_2).coordinates().x()
2001 sk_coo_y_2 = SketchAPI_Point(SketchPoint_2).coordinates().y()
2003 SketchProjection_3 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
2004 SketchLine_0 = SketchProjection_3.createdFeature()
2006 # 6.2. Lignes perpendiculaires à l'axe passant par les centres
2007 SketchLine_1 = sketch.addLine(sk_coo_x_1, sk_coo_y_1, sk_coo_x_1+rayon_1, sk_coo_y_1)
2008 SketchLine_1.setAuxiliary(True)
2009 sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.startPoint())
2010 sketch.setPerpendicular(SketchLine_0.result(), SketchLine_1.result())
2011 sketch.setLength(SketchLine_1.result(), nom_par_1)
2013 SketchLine_2 = sketch.addLine(sk_coo_x_2, sk_coo_y_2, sk_coo_x_2+rayon_2, sk_coo_y_2)
2014 SketchLine_2.setAuxiliary(True)
2015 sketch.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_2.startPoint())
2016 sketch.setPerpendicular(SketchLine_0.result(), SketchLine_2.result())
2017 sketch.setLength(SketchLine_2.result(), nom_par_2)
2019 # 6.3. Ligne joignant les extrémités des précédentes et point milieu
2020 SketchLine_3 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
2021 sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_1.endPoint())
2022 sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_2.endPoint())
2023 SketchLine_3.setAuxiliary(True)
2024 SketchPoint_3 = sketch.addPoint(sk_coo_x_1, sk_coo_y_1)
2025 sketch.setMiddlePoint(SketchLine_3.result(), SketchPoint_3.coordinates())
2027 # 6.4. Ligne support de la future révolution
2028 SketchLine_4 = sketch.addLine(sk_coo_x_1+rayon_1, sk_coo_y_1, sk_coo_x_2+rayon_2, sk_coo_y_2)
2029 sketch.setMiddlePoint(SketchLine_4.result(), SketchPoint_3.coordinates())
2030 sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_4.result())
2031 sketch.setLength(SketchLine_4.result(), "1.2*{}".format(nom_par_3))
2034 nom_sketch = "{}_esquisse".format(self.nom_solide)
2035 sketch.setName(nom_sketch)
2036 sketch.result().setName(nom_sketch)
2038 # Création du cone complet
2039 nom_cone = "{}_cone".format(self.nom_solide)
2040 self._cree_revolution ( nom_sketch, nom_centre_1, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
2042 # Intersection de la face conique avec le solide initial
2043 face = self._creation_face_inter ( nom_cone )
2047 #=========================== Fin de la méthode ==================================
2049 #=========================== Début de la méthode =================================
2051 def _cree_centre_axe_plan ( self, coo_c, vnor, prefixe, n_recur ):
2052 """Crée un centre, un axe, un plan
2057 :coo_c: coordonnées du centre de la base
2058 :vnor: coordonnées du vecteur normal
2059 :prefix: prefixe du nom des objets
2060 :n_recur: niveau de récursivité
2064 :normal: vecteur normal
2068 nom_fonction = __name__ + "/_cree_centre_axe_plan"
2069 blabla = "Dans {} :".format(nom_fonction)
2070 if self._verbose_max:
2071 print_tab (n_recur, blabla)
2072 print_tab (n_recur, "Centre : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
2073 print_tab (n_recur, "Normale : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
2075 # Création du point central
2076 centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
2077 nom_centre = "{}_centre".format(prefixe)
2078 nommage (centre, nom_centre)
2081 # Création du vecteur normal
2082 v_norm = model.addAxis(self.part_doc, vnor[0], vnor[1], vnor[2])
2083 nom_vnorm = "{}_normale".format(prefixe)
2084 nommage (v_norm, nom_vnorm)
2086 # Création du plan perpendiculaire au vecteur normal
2087 plan = model.addPlane(self.part_doc, model.selection("EDGE", v_norm.name()), model.selection("VERTEX", centre.name()), True)
2088 nom_plan = "{}_plan".format(prefixe)
2089 nommage (plan, nom_plan)
2091 #print ("fin de {}".format(nom_fonction))
2093 return centre, v_norm, plan
2095 #=========================== Fin de la méthode ==================================
2097 #=========================== Début de la méthode =================================
2099 def _calcul_boite_englobante ( self, objet, n_recur ):
2100 """Crée la hauteur englobant à coup sûr l'objet
2103 :objet: l'objet à traiter
2104 :n_recur: niveau de récursivité
2107 :l_diag: longueur de la diagonale de la boîte englobante
2110 nom_fonction = __name__ + "/_calcul_boite_englobante"
2111 blabla = "Dans {} :".format(nom_fonction)
2113 if self._verbose_max:
2114 print_tab (n_recur, blabla)
2116 # Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
2117 if self._verbose_max:
2118 print_tab (n_recur, "Création de la boite englobante pour l'objet ", objet.name())
2119 print_tab (n_recur, "de type ", objet.shapeType())
2120 #print ('bbox = model.getBoundingBox(self.part_doc, model.selection("{}", "{}"))'.format(objet.shapeType(),objet.name()))
2121 bbox = model.getBoundingBox(self.part_doc, model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
2124 bbox_nom = bbox.result().name()
2125 if self._verbose_max:
2126 print_tab (n_recur, "Boîte englobante : '{}' '{}'".format(bbox.name(), bbox_nom))
2128 if self._verbose_max:
2129 coo_min = model.getPointCoordinates(self.part_doc, \
2130 model.selection("VERTEX", "[{}/Back][{}/Left][{}/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)))
2131 coo_max = model.getPointCoordinates(self.part_doc, \
2132 model.selection("VERTEX", "[{}/Front][{}/Right][{}/Top]".format(bbox_nom,bbox_nom,bbox_nom)))
2133 texte = "Xmin = {}, Xmax = {}\n".format(coo_min[0],coo_max[0])
2134 texte += "\tYmin = {}, Ymax = {}\n".format(coo_min[1],coo_max[1])
2135 texte += "\tZmin = {}, Zmax = {}".format(coo_min[2],coo_max[2])
2136 print_tab (n_recur, texte)
2138 l_diag = model.measureDistance(self.part_doc, \
2139 model.selection("VERTEX", "[{}/Back][{}/Left][{}/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)), \
2140 model.selection("VERTEX", "[{}/Front][{}/Right][{}/Top]".format(bbox_nom,bbox_nom,bbox_nom)) )
2141 if self._verbose_max:
2142 print_tab (n_recur, "Longueur de la diagonale : ", l_diag)
2146 #=========================== Fin de la méthode ==================================
2148 #=========================== Début de la méthode =================================
2150 def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
2151 """Crée un volume de révolution
2154 :nom_sketch: nom de l'esquisse à révolutionner
2155 :nom_centre: nom du point associé au centre du volume de révolution
2156 :coo_x, coo_y, coo_z: coordonnées du centre du tore
2157 :axe_x, axe_y, axe_z: coordonnées de l'axe
2158 :rayon_1 : rayon principal
2159 :rayon_2 : rayon secondaire
2160 :nom_objet: nom de l'objet 2D créé
2163 nom_fonction = __name__ + "/_cree_revolution"
2164 blabla = "Dans {} :\n".format(nom_fonction)
2166 if self._verbose_max:
2168 texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2169 texte += "Axe : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2172 # Création d'un point décalé par rapport au point central
2173 point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
2174 nom_point = "{}_point".format(self.nom_solide)
2175 point.result().setName(nom_point)
2177 # Création de l'axe de la rotation
2178 axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
2179 nom_axe_r = "{}_axe_r".format(self.nom_solide)
2180 axe_r.result().setName(nom_axe_r)
2182 # Création de l'objet complet
2183 objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
2185 nommage (objet, nom_objet, (85, 0, 255))
2189 #=========================== Fin de la méthode ==================================
2191 #=========================== Début de la méthode =================================
2193 def _creation_face_inter ( self, nom_objet ):
2194 """Crée la face par intersection entre l'objet initial et une face complète
2196 . Repère la face principale de l'objet support
2197 . Réalise l'intersection avec le solide initial
2200 :nom_objet: nom de l'objet 2D créé
2203 :face: la face externe de l'objet support intersecté avec le solide initial
2206 nom_fonction = __name__ + "/_creation_face_inter"
2207 blabla = "Dans {} :\n".format(nom_fonction)
2209 if self._verbose_max:
2212 face = model.addCommon(self.part_doc, [model.selection("SOLID", self.nom_solide_aux), model.selection("FACE", nom_objet)], keepSubResults = True)
2216 #=========================== Fin de la méthode ==================================
2218 #=========================== Début de la méthode =================================
2220 def face_mediane_solide (self, solide, n_recur=0):
2221 """Calcul de la face médiane pour un solide
2224 :solide: solide SHAPER à traiter
2225 :n_recur: niveau de récursivité
2228 :erreur: code d'erreur
2229 :message: message d'erreur
2232 nom_fonction = __name__ + "/face_mediane_solide"
2233 blabla = "Dans {} :".format(nom_fonction)
2235 if self._verbose_max:
2236 print_tab (n_recur, blabla, saut_av=True)
2238 print_tab (n_recur, "Traitement du solide ", solide.name())
2247 # 2. Calcul des caractéristiques géométriques des faces
2249 tb_caract = self._calcul_caract_faces ( solide, n_recur )
2251 # 3. Tri des faces en fonction de leurs caractéristiques géométriques
2253 erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract, n_recur )
2257 # 4. Création de la face médiane
2259 erreur, face = self._cree_face_mediane ( solide, caract_face_1, caract_face_2, n_recur )
2263 # 6. Exportation step
2265 if self._export_step:
2266 fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2267 export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2268 export.execute(True)
2275 if ( erreur and self._verbose_max ):
2276 print (blabla, message)
2278 return erreur, message
2280 #=========================== Fin de la méthode ==================================
2282 #=========================== Début de la méthode =================================
2284 def _traitement_objet (self, solide, n_recur=0):
2285 """Traitement d'un objet
2288 :solide: solide SHAPER à traiter
2289 :n_recur: niveau de récursivité
2292 :erreur: code d'erreur
2293 :message: message d'erreur
2296 nom_fonction = __name__ + "/_traitement_objet"
2297 blabla = "Dans {} :".format(nom_fonction)
2299 if self._verbose_max:
2300 print_tab (n_recur, blabla, saut_av=True)
2301 texte = "solide = {} ".format(solide.name())
2302 print_tab (n_recur, texte, solide)
2304 # 1. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2305 # Attention à ne pas recréer le répertoire à chaque fois
2306 if self._export_step:
2308 if self.rep_step is None:
2310 if self._verbose_max:
2311 print_tab (n_recur, "Préparation de l'export STEP")
2313 if self.ficcao is None:
2314 self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2316 self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2317 if os.path.isdir(self.rep_step):
2318 l_aux = os.listdir(self.rep_step)
2319 for nomfic in l_aux:
2320 os.remove(os.path.join(self.rep_step,nomfic))
2322 os.mkdir(self.rep_step)
2324 if self._verbose_max:
2325 print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2327 # 2. Calcul réel de la face médiane
2329 erreur, message = self.face_mediane_solide (solide, n_recur)
2331 return erreur, message
2333 #=========================== Fin de la méthode ==================================
2335 #=========================== Début de la méthode =================================
2337 def surf_fic_cao (self, ficcao, nom_objet=None):
2338 """Calcule la surface médiane pour un objet dans un fichier passé en argument
2341 :ficcao: fichier de l'objet à traiter
2342 :nom_objet: un nom à donner à l'objet à traiter
2345 :erreur: code d'erreur
2346 :message: message d'erreur
2349 nom_fonction = __name__ + "/surf_fic_cao"
2350 blabla = "Dans {} :".format(nom_fonction)
2352 if self._verbose_max:
2362 if self.affiche_aide_globale:
2365 # 1. Définition de la pièce
2367 self.part_doc = model.activeDocument()
2368 if ( self.part_doc.kind() == "PartSet" ):
2369 part = model.addPart(self.part_doc)
2370 self.part_doc = part.document()
2372 # 2. Import de la CAO
2374 self.ficcao = ficcao
2375 print ("Traitement du fichier {}".format(ficcao))
2377 erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2381 # 3. Calcul des surfaces
2383 erreur, message = self.surf_objet_shaper ( objet )
2392 if ( erreur and self._verbose_max ):
2393 print (blabla, message)
2395 return erreur, message
2397 #=========================== Fin de la méthode ==================================
2399 #=========================== Début de la méthode =================================
2401 def surf_objet_shaper (self, objet):
2402 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2405 :objet: objet à traiter
2408 :erreur: code d'erreur
2409 :message: message d'erreur
2412 nom_fonction = __name__ + "/surf_objet_shaper"
2413 blabla = "Dans {} :".format(nom_fonction)
2415 if self._verbose_max:
2423 if self.affiche_aide_globale:
2426 # 1. Acquisition de la liste des noms des sous-objets solides
2428 self.d_statut_so = dict()
2429 self.l_noms_so = list()
2430 self.l_faces_m = list()
2432 _ = self._nom_sous_objets (objet, True)
2433 if self._verbose_max:
2434 print ("Noms des sous-objets : {}".format(self.l_noms_so))
2436 # 2. Les faces médianes
2438 erreur, message = self._surf_objet_shaper_0 ( objet )
2442 # 3. Gestion des faces créées
2444 self._surf_objet_shaper_1 ( )
2446 # 4. Futur message pour le résultat
2448 if ( self._export_step and not erreur ):
2449 message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2453 return erreur, message
2455 #=========================== Fin de la méthode ==================================
2457 #=========================== Début de la méthode =================================
2459 def _surf_objet_shaper_0 (self, objet, n_recur=0):
2460 """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2463 :objet: objet à traiter
2464 :n_recur: niveau de récursivité
2467 :erreur: code d'erreur
2468 :message: message d'erreur
2471 nom_fonction = __name__ + "/_surf_objet_shaper_0"
2472 blabla = "Dans {} :".format(nom_fonction)
2474 if self._verbose_max:
2475 print_tab (n_recur, blabla)
2476 print_tab (n_recur, "n_recur = ", n_recur)
2483 # 1. Au premier passage, il faut récupérer la pièce SHAPER et garder la référence au résultat principal
2485 if ( n_recur == 0 ):
2486 self.part_doc = model.activeDocument()
2487 objet_0 = objet.result()
2488 self.objet_principal = objet_0
2489 objet_bis = objet.defaultResult().shape()
2490 if self._verbose_max:
2491 print_tab (0, "Examen de l'objet initial ", objet.result().name(), saut_av=True)
2492 print_tab (0, "Type python : ", type(objet))
2493 print_tab (0, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2496 if self._verbose_max:
2497 print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2498 print_tab (n_recur, "Type python : ", type(objet))
2499 print_tab (n_recur, "shapeType : ", objet.shapeType())
2501 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2503 nb_sub_results = objet_0.numberOfSubs()
2505 if self._verbose_max:
2506 print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType(), saut_av=True)
2507 print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2509 for n_sobj in range(nb_sub_results):
2511 # 2.1. Exploration récursive de l'arborescence
2513 erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2520 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2522 if ( objet_0.shapeType() == "SOLID" ):
2523 erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2527 # 3. Futur message pour le résultat
2529 if self._export_step:
2530 message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2534 return erreur, message
2536 #=========================== Fin de la méthode ==================================
2538 #=========================== Début de la méthode =================================
2540 def _surf_objet_shaper_1 (self, n_recur=0):
2541 """Gestion des surfaces médianes créées
2544 :n_recur: niveau de récursivité
2547 :erreur: code d'erreur
2548 :message: message d'erreur
2551 nom_fonction = __name__ + "/_surf_objet_shaper_1"
2552 blabla = "Dans {} :\n".format(nom_fonction)
2554 if self._verbose_max:
2555 print_tab (n_recur, blabla)
2557 # 1. Informations sur les faces à problème
2559 if self.faces_pb_nb:
2560 if ( self.faces_pb_nb == 1 ):
2561 texte = "1 face pose"
2563 texte = "{} faces posent".format(self.faces_pb_nb)
2564 print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2566 # 2. Si plus d'une face a été créée
2567 if ( len(self.l_faces_m) > 1 ):
2569 # 2.1. Partition du paquet de faces
2571 if self._verbose_max:
2572 print_tab (n_recur, "Partitionnnement des faces créées.")
2574 # 2.1.1. Pour une raison mystérieuse, il faut commencer par les faces entières, puis mettre les sous-faces éventuelles
2576 for (face,_) in self.l_faces_m:
2577 if not face.result().numberOfSubs():
2578 d_faces[face.name()] = [face.name()]
2579 for (face,_) in self.l_faces_m:
2580 nb_sub_results = face.result().numberOfSubs()
2583 for n_sobj in range(nb_sub_results):
2584 laux.append(face.result().subResult(n_sobj).name())
2585 d_faces[face.name()] = laux
2588 for _, laux in d_faces.items():
2589 for s_face_n in laux:
2590 l_objets.append(model.selection("FACE", s_face_n))
2592 Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2594 Partition_1.result().setName("{}_M".format(self.objet_principal.name()))
2596 for face_n, laux in d_faces.items():
2597 Partition_1.result().subResult(iaux).setName("{}".format(face_n))
2598 if ( len(laux) > 1 ):
2599 for jaux, s_face_n in enumerate(laux):
2600 Partition_1.result().subResult(iaux).subResult(jaux).setName("{}_M".format(s_face_n))
2602 self._couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0)
2604 # 2.2. Récupération des faces individuelles
2606 if self._verbose_max:
2607 print_tab (n_recur, "Récupération des faces individuelles.")
2610 for iaux, (face,_) in enumerate(self.l_faces_m):
2611 l_objets.append(face.result())
2613 Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2614 for iaux, (face,_) in enumerate(self.l_faces_m):
2615 Recover_1.results()[iaux].setName("{}".format(face.name()))
2616 Recover_1.results()[iaux].setColor(0, 170, 0)
2617 nb_sub_results = Recover_1.results()[iaux].numberOfSubs()
2618 for n_sobj in range(nb_sub_results):
2619 Recover_1.results()[iaux].subResult(n_sobj).setName("{}_{}".format(face.name(),n_sobj))
2620 Recover_1.results()[iaux].subResult(n_sobj).setColor(0, 170, 0)
2622 # 2.3. Mise en dossier
2624 if self._verbose_max:
2625 print_tab (n_recur, "Mise en dossier.")
2627 for (face,fonction_0) in self.l_faces_m:
2628 dossier = model.addFolder(self.part_doc, fonction_0, face)
2629 dossier.setName(face.name()[:-2])
2630 dossier = model.addFolder(self.part_doc, Partition_1, Recover_1)
2631 dossier.setName(self.objet_principal.name())
2635 #=========================== Fin de la méthode ==================================
2637 #=========================== Début de la méthode =================================
2639 def surf_solide_shaper (self, solide, n_recur):
2640 """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2643 :solide: solide SHAPER à traiter
2644 :n_recur: numéro de la récurrence
2647 :erreur: code d'erreur
2648 :message: message d'erreur
2651 nom_fonction = __name__ + "/surf_solide_shaper"
2652 blabla = "Dans {} :".format(nom_fonction)
2654 if self._verbose_max:
2655 print_tab (n_recur, blabla, saut_av=True)
2662 self.nom_solide = solide.name()
2663 if self._verbose_max:
2664 print_tab (n_recur, "solide : ", self.nom_solide)
2666 # 1. Isolement du solide
2667 solide_aux, recover = self._isole_solide ( solide, n_recur )
2669 # 2. Traitement de l'objet correspondant
2670 erreur, message = self._traitement_objet ( solide_aux, n_recur=n_recur )
2672 if ( erreur and self._verbose_max ):
2673 print (blabla, message)
2675 # 3. Neutralisation des erreurs dues à l'épaisseur
2676 if ( erreur in (-2,-1,2) ):
2682 # 4. Mise en forme de l'objet principal récupéré
2683 if ( recover is not None ):
2684 _ = self._nom_sous_objets (recover, False)
2688 return erreur, message
2690 #=========================== Fin de la méthode ==================================
2692 #========================== Fin de la classe ====================================
2694 #==================================================================================
2696 #==================================================================================
2698 if __name__ == "__main__" :
2700 HOME_SH_SM_EXCHANGE = os.environ["HOME_SH_SM_EXCHANGE"]
2702 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "Solid_7.step"))
2703 L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Objet_1.stp"))
2704 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval_007.stp"))
2705 ##L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval.stp"))
2706 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2.step"))
2707 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_22.step"))
2708 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_5.step"))
2709 #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Observatoire.stp"))
2711 for FIC_CAO in L_FIC_CAO:
2716 #L_OPTIONS.append("-h")
2717 #L_OPTIONS.append("-v")
2718 L_OPTIONS.append("-vmax")
2719 L_OPTIONS.append("-export_step")
2721 # 2. Lancement de la classe
2723 #print ("L_OPTIONS :", L_OPTIONS)
2725 SURFACE_MEDIANE = SurfaceMediane(L_OPTIONS)
2726 if SURFACE_MEDIANE.affiche_aide_globale:
2727 sys.stdout.write(SURFACE_MEDIANE.__doc__+"\n")
2730 PARTSET = model.moduleDocument()
2731 _ = model.addPart(PARTSET)
2732 ERREUR, MESSAGE_ERREUR = SURFACE_MEDIANE.surf_fic_cao(FIC_CAO)
2734 MESSAGE_ERREUR += "\n Code d'erreur : %d\n" % ERREUR
2735 sys.stderr.write(MESSAGE_ERREUR)