Salome HOME
suite
[modules/shaper.git] / src / PythonAddons / macros / midSurface / surfaceMediane.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2016-2022  CEA/DEN, EDF R&D
3 #
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.
8 #
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.
13 #
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
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 """Obtention des surfaces médianes à partir d'un objet GEOM ou SHAPER
21
22 On sait traiter les faces :
23   . planes
24   . cylindriques
25   . sphériques
26   . toriques
27   . coniques
28
29 Pour un objet complexe, on crée l'objet final comme étant la partition de toutes
30 les surfaces médianes.
31
32 Version initiale par :
33 alexandre.prunie@blastsolutions.io
34 guillaume.schweitzer@blastsolutions.io
35
36 Gérald NICOLAS
37 """
38
39 __revision__ = "V10.56"
40
41 #========================= Les imports - Début ===================================
42
43 import os
44 import sys
45 import tempfile
46
47 import salome
48
49 salome.standalone()
50 salome.salome_init()
51
52 import SALOMEDS
53 from SketchAPI import *
54 from salome.shaper import model
55 from GeomAPI import *
56 from GeomAlgoAPI import *
57
58 from salome.geom import geomBuilder
59
60 import numpy as np
61
62 #========================== Les imports - Fin ====================================
63
64 D_FMT = dict()
65 D_FMT["stp"] = ["stp", "step"]
66 D_FMT["igs"] = ["igs", "iges"]
67 for CLE in ("brep", "xao"):
68   D_FMT[CLE] = [CLE]
69
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.
71 D_COLOR_R = dict()
72 D_COLOR_G = dict()
73 D_COLOR_B = dict()
74 D_COLOR_R[-2] = 255
75 D_COLOR_G[-2] = 255
76 D_COLOR_B[-2] = 0
77 D_COLOR_R[-1] = 255
78 D_COLOR_G[-1] = 0
79 D_COLOR_B[-1] = 0
80 D_COLOR_R[0] = 50
81 D_COLOR_G[0] = 50
82 D_COLOR_B[0] = 50
83 D_COLOR_R[1] = 170
84 D_COLOR_G[1] = 255
85 D_COLOR_B[1] = 120
86 D_COLOR_R[2] = 0
87 D_COLOR_G[2] = 0
88 D_COLOR_B[2] = 255
89 # Transparence des solides traités correctement
90 TRANSPARENCE = 0.7
91
92 # Limite basse de l'épaisseur pour pouvoir faire les intersections
93 EP_MIN = 0.0001
94 #EP_MIN = 0.1
95 #========================= Début de la fonction ==================================
96
97 def decode_cao (fmt_cao):
98   """Décode le format de la cao
99
100 Entrées :
101   :fmt_cao: format du fichier, step, iges, etc.
102 Sorties :
103   :fmt_cao_0: format décodé
104   """
105
106   fmt_cao_0 = ""
107
108   fmt_cao_low = fmt_cao.lower()
109
110   for cle, l_aux in D_FMT.items():
111     if ( fmt_cao_low in l_aux ):
112       fmt_cao_0 = cle
113       break
114
115   return fmt_cao_0
116
117 #=========================  Fin de la fonction ===================================
118
119 #========================= Début de la fonction ==================================
120
121 def import_cao (part_doc, ficcao, nom_objet=None, verbose=False):
122   """Importation d'une cao
123
124 Entrées :
125   :part_doc: part
126   :ficcao: le fichier de la CAO
127   :nom_objet: nom à donner à l'objet lu, éventuellement
128 Sorties :
129   :objet: l'objet importé dans SHAPER
130   """
131
132   nom_fonction = __name__ + "/import_cao"
133   blabla = "Dans {} :\n".format(nom_fonction)
134   message_0 = "Fichier : {}\n".format(ficcao)
135   if verbose:
136     message = blabla + message_0
137     message += "nom_objet : {}".format(nom_objet)
138     print (message)
139     message = message_0
140
141   erreur = 0
142
143   objet = None
144
145   laux = ficcao.split(".")
146   fmt_cao_0 = decode_cao (laux[-1])
147
148   if ( fmt_cao_0 not in ("stp", "brep", "igs", "xao") ):
149     message += "Le format de CAO est inconnu"
150     erreur = 1
151
152   elif not ficcao:
153     message += "Le fichier de CAO n'a pas été décodé correctement."
154     erreur = 2
155
156   elif not os.path.isfile(ficcao):
157     message += "Le fichier de CAO est inconnu."
158     erreur = 3
159
160   else:
161
162     message = ""
163     objet = model.addImport(part_doc, ficcao)
164     objet.execute(True)
165     model.do()
166
167     if nom_objet is not None:
168       objet.result().setName(nom_objet)
169
170     if verbose:
171       texte  = "Objet   : '{}'\n".format(objet.result().name())
172       texte += "De type : '{}'".format(objet.result().shapeType())
173       print (texte)
174
175   return erreur, message, objet
176
177 #=========================  Fin de la fonction ===================================
178
179 #========================= Début de la fonction ==================================
180
181 def print_tab (nb_tab, message, argu=None, saut_av=False, saut_ap=False):
182   """Imprime avec des tabulations
183
184 Entrées :
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
190   """
191
192   texte = ""
193
194   if saut_av:
195     texte += "\n"
196
197   for _ in range(nb_tab):
198     texte += "\t"
199
200   texte += message
201   if ( argu is not None ):
202     texte += "{}".format(argu)
203
204   if saut_ap:
205     texte += "\n"
206
207   print (texte)
208
209 #=========================  Fin de la fonction ===================================
210
211 #========================= Début de la fonction ==================================
212
213 def nommage (objet, nom, couleur=None):
214   """Nomme un objet et son résultat
215
216 Entrées :
217   :objet: objet à traiter
218   :nom: nom à attribuer
219   :couleur: éventuellement couleur
220   """
221
222   objet.setName(nom)
223   objet.result().setName(nom)
224
225   if ( couleur is not None ):
226     objet.result().setColor(couleur[0], couleur[1], couleur[2])
227
228 #=========================  Fin de la fonction ===================================
229
230
231 #=================================== La classe ===================================
232
233 class SurfaceMediane (object):
234
235   """Calcul des surfaces médianes de solides minces
236
237 L'objectif de ce programme est de créer les surfaces médianes, encore appelées fibres neutres, pour \
238 une structure qui est un solide ou un assemblage de solides (compound).
239 Pour réaliser l'opération, trois façons de faire :
240
241 1. On lance le script en précisant le fichier à analyser dans la zone d'auto-test.
242
243 2. Si on part d'un script qui manipule un fichier au format CAO, on crée une instance de la classe SurfaceMediane \
244 puis on appelle la méthode surf_fic_cao avec ce fichier en argument.
245
246 3. Si on part d'un script qui crée un objet SHAPER, on crée une instance de la classe SurfaceMediane \
247 puis on appelle la méthode surf_objet_shaper avec cet objet en argument.
248
249
250 Le programme crée les surfaces sous réserve que pour le solide envisagé, il a réussi à trouver deux faces \
251 de taille identique et supérieure aux tailles des autres faces du solide. \
252 Cela fonctionne pour des surfaces planes ou de forme canonique.
253 Il crée alors une surface au milieu de ces deux grandes faces. \
254 Cette face est coloriée en vert, le solide est en vert et transparent.
255
256 On sait traiter les faces :
257   . planes
258   . cylindriques
259   . sphériques
260   . toriques
261   . coniques
262
263 Si la création n'a pas eu lieu, un message est émis et les solides sont mis en couleur :
264 . Rouge : le solide n'est pas assez mince.
265 . Bleu : le solide est trop mince, vis-à-vis de la précision de SHAPER.
266 . Orange : la forme de la face n'est pas reconnue.
267
268 Options obligatoires
269 ********************
270 Aucune
271
272 Options facultatives
273 ********************
274 . Exportation finale dans un fichier step. Par défaut, pas d'export.
275 -export_step/-no_export_step
276
277 Arborescence :
278 surf_fic_cao --> import_cao
279              --> surf_objet_shaper (récursif) --> _nom_sous_objets
280                                               --> _surf_objet_shaper_0
281                                               --> surf_solide_shaper --> _isole_solide
282                                                                      --> _traitement_objet --> face_mediane_solide --> _faces_du_solide
283                                                                                                                    --> _tri_faces
284                                                                                                                    --> _cree_face_mediane
285
286 _cree_face_mediane --> _cree_face_mediane_plane
287                    --> _cree_face_mediane_cylindre
288                    --> _cree_face_mediane_sphere
289                    --> _cree_face_mediane_tore
290                    --> _cree_face_mediane_cone
291                    --> _cree_face_mediane_0
292
293   """
294
295 # A. La base
296
297   message_info = ""
298   _verbose = 0
299   _verbose_max = 0
300   affiche_aide_globale = 0
301
302 # B. Les variables
303
304   _choix_objet = 0
305   _export_step = False
306   nom_solide = None
307   nom_solide_aux = None
308   _epsilon = 5.e-2
309   part_doc = None
310
311   ficcao = None
312   rep_step = None
313   objet_principal = None
314   objet_geom = None
315   # Pour chaque sous-objet dans l'ordre de l'arborescence : nom
316   l_noms_so = list()
317   # Statut de chaque sous-objet connu par son nom :
318   # 0 si pas encore traité, 1 si traité avec succès, 2 si trop mince, -1 si pas assez mince, -2 si impossible.
319   d_statut_so = dict()
320   # Liste des faces médianes créées et des fonctions initiales
321   l_faces_m = list()
322   # La fonction initiale
323   fonction_0 = None
324
325   faces_pb_nb = 0
326   faces_pb_msg = ""
327
328 #=========================== Début de la méthode =================================
329
330   def __init__ ( self, liste_option ):
331
332     """Le constructeur de la classe SurfaceMediane
333
334 Décodage des arguments
335 On cherche ici les arguments généraux : aide, verbeux
336 """
337
338     for option in liste_option :
339
340       #print (option)
341       if isinstance(option,str):
342         saux = option.upper()
343       #print (saux)
344       if saux in ( "-H", "-HELP" ):
345         self.affiche_aide_globale = 1
346       elif saux == "-V" :
347         self._verbose = 1
348       elif saux == "-VMAX" :
349         self._verbose = 1
350         self._verbose_max = 1
351       elif saux == "-EXPORT_STEP":
352         self._export_step = True
353       elif saux == "-NO_EXPORT_STEP":
354         self._export_step = False
355
356 #===========================  Fin de la méthode ==================================
357
358 #=========================== Début de la méthode =================================
359
360   def __del__(self):
361     """A la suppression de l'instance de classe"""
362     if self._verbose_max:
363       print ("Suppression de l'instance de la classe.")
364
365 #===========================  Fin de la méthode ==================================
366
367 #=========================== Début de la méthode =================================
368
369   def _nom_sous_objets (self, objet, lecture, n_recur=0, rang=0):
370     """Gère les noms des sous_objets solides
371
372 Entrées :
373   :objet: objet à traiter
374   :lecture: vrai pour lire les noms, faux pour les attribuer
375   :n_recur: niveau de récursivité
376   :rang: rang du sous-objet
377
378 Sorties :
379   :rang: rang du sous-objet
380 """
381
382     nom_fonction = __name__ + "/_nom_sous_objets"
383     blabla = "Dans {} :\n".format(nom_fonction)
384
385     if self._verbose_max:
386       prefixe = ""
387       for _ in range(n_recur):
388         prefixe += "\t"
389       texte = "\n{}{}".format(prefixe,blabla)
390       texte += "{}n_recur = {}".format(prefixe,n_recur)
391       texte += "\n{}lecture = {}".format(prefixe,lecture)
392       print (texte)
393
394 # 1. Au premier passage, il faut garder la référence au résultat principal
395
396     if ( n_recur ==  0 ):
397       objet_0 = objet.result()
398       if self._verbose_max:
399         print ("d_statut_so = {}".format(self.d_statut_so))
400     else:
401       objet_0 = objet
402
403 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
404
405     nb_sub_results = objet_0.numberOfSubs()
406
407     if self._verbose_max:
408       texte = "{}Examen de l'objet '{}' ".format(prefixe,objet_0.name())
409       texte += "de type '{}'".format(objet_0.shapeType())
410       texte += "\n{}objet.result().numberOfSubs() : {}".format(prefixe,nb_sub_results)
411       print (texte)
412
413     for n_sobj in range(nb_sub_results):
414
415 # 2.1. Exploration récursive de l'arborescence
416
417       rang = self._nom_sous_objets ( objet_0.subResult(n_sobj), lecture, n_recur+1, rang )
418
419 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
420
421     if ( objet_0.shapeType() == "SOLID" ):
422       # A la lecture, on enregistre le nom
423       if lecture:
424         nom = objet_0.name()
425         self.l_noms_so.append(nom)
426         self.d_statut_so[nom] = 0
427       # A la récupération, on redonne le nom et on affecte une couleur dépendant de l'état
428       else:
429         nom = self.l_noms_so[rang]
430         objet_0.setName(nom)
431         etat = self.d_statut_so[nom]
432         objet_0.setColor (D_COLOR_R[etat],D_COLOR_G[etat],D_COLOR_B[etat])
433         if ( etat == 1 ):
434           objet_0.setTransparency (TRANSPARENCE)
435         rang += 1
436
437     return rang
438
439 #===========================  Fin de la méthode ==================================
440
441 #=========================== Début de la méthode =================================
442
443   def _couleur_objet (self, objet, n_recur=0, coul_r=1, coul_g=0, coul_b=0):
444     """Appliquer une couleur à un objet et à ses sous_objets
445
446 Entrées :
447   :objet: objet à traiter
448   :n_recur: niveau de récursivité
449   :coul_r,coul_g,coul_b: code RGB de la couleur à appliquer
450
451 Sorties :
452   :rang: rang du sous-objet
453 """
454
455     nom_fonction = __name__ + "/_couleur_objet"
456     blabla = "Dans {} :".format(nom_fonction)
457
458     if self._verbose_max:
459       print (blabla)
460       print_tab(n_recur, "objet : ", objet.name())
461       print_tab(n_recur, "RGB = ({},{},{})".format(coul_r,coul_g,coul_b))
462
463 # 1. Au premier passage, il faut garder la référence au résultat principal
464
465     if ( n_recur == 0 ):
466       objet_0 = objet.result()
467     else:
468       objet_0 = objet
469
470 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
471
472     nb_sub_results = objet_0.numberOfSubs()
473
474     if self._verbose_max:
475       print_tab(n_recur, "Examen de l'objet ",objet_0.name())
476       texte = "de type '{}' ".format(objet_0.shapeType())
477       texte += "et de {} sous-objets".format(nb_sub_results)
478       print_tab(n_recur, texte)
479
480     for n_sobj in range(nb_sub_results):
481
482 # 2.1. Exploration récursive de l'arborescence
483
484       self._couleur_objet ( objet_0.subResult(n_sobj), n_recur+1, coul_r, coul_g, coul_b )
485
486 # 2.2. Cet objet n'a pas de sous-objets : on le colore
487     if self._verbose_max:
488       print_tab(n_recur, "Couleur affectée à l'objet ",objet_0.name())
489     objet_0.setColor (int(coul_r),int(coul_g),int(coul_b))
490
491     #print ("sortie de {}".format(nom_fonction))
492
493     return
494
495 #===========================  Fin de la méthode ==================================
496
497 #=========================== Début de la méthode =================================
498
499   def _isole_solide ( self, solide, n_recur ):
500     """Isole le solide de son arboresence
501
502 Entrées :
503   :solide: le solide à traiter
504   :n_recur: numéro de la récurrence
505
506 Sorties :
507   :objet: le solide isolé
508   :recover: la fonction de récupération
509 """
510
511     nom_fonction = __name__ + "/_isole_solide"
512     blabla = "Dans {} :".format(nom_fonction)
513     if self._verbose_max:
514       print_tab (n_recur, blabla)
515       texte = "Pour le solide '{}' ".format(solide.name())
516       texte += "de l'objet principal '{}'".format(self.objet_principal.name())
517       print_tab (n_recur, texte)
518
519     if ( solide.name() != self.objet_principal.name() ):
520       objet, recover = self._isole_solide_a ( solide, n_recur )
521
522     else:
523       objet, recover = self._isole_solide_b ( solide, n_recur )
524
525     if self._verbose_max:
526       print_tab (n_recur, "objet final : ", objet.name())
527       print_tab (n_recur, "fonction_0 : ", self.fonction_0)
528       print_tab (n_recur, "recover : ", recover)
529
530     return objet, recover
531
532 #===========================  Fin de la méthode ==================================
533
534 #=========================== Début de la méthode =================================
535
536   def _isole_solide_a ( self, solide, n_recur ):
537     """Isole le solide de son arboresence
538
539 Entrées :
540   :solide: le solide à traiter
541   :n_recur: numéro de la récurrence
542
543 Sorties :
544   :objet: le solide isolé
545   :recover: la fonction de récupération
546 """
547
548     nom_fonction = __name__ + "/_isole_solide_a"
549     blabla = "Dans {} :".format(nom_fonction)
550     if self._verbose_max:
551       print_tab (n_recur, blabla)
552       texte = "Pour le solide '{}' ".format(solide.name())
553       texte += "de l'objet principal '{}'".format(self.objet_principal.name())
554       print_tab (n_recur, texte)
555
556     if self._verbose_max:
557       print_tab (n_recur, ". Extraction du solide '{}'".format(self.objet_principal.name()))
558
559 # 1. Extraction du solide
560     remove_subshapes = model.addRemoveSubShapes(self.part_doc, model.selection("COMPOUND", self.objet_principal.name()))
561     remove_subshapes.setSubShapesToKeep([model.selection("SOLID", solide.name())])
562
563     self.nom_solide_aux = "{}_S".format(solide.name())
564     if self._verbose_max:
565       print_tab (n_recur, "\tAttribution à remove_subshapes.result() du nom '{}'".format(self.nom_solide_aux))
566     remove_subshapes.result().setName(self.nom_solide_aux)
567
568     self.fonction_0 = remove_subshapes
569
570 # 2. Récupération de l'objet principal
571     recover = model.addRecover(self.part_doc, remove_subshapes, [self.objet_principal])
572     if self._verbose_max:
573       print_tab (n_recur, "\tAttribution à recover du nom '{}'".format(self.objet_principal.name()))
574     recover.result().setName(self.objet_principal.name())
575
576     return remove_subshapes.result(), recover
577
578 #===========================  Fin de la méthode ==================================
579
580 #=========================== Début de la méthode =================================
581
582   def _isole_solide_b ( self, solide, n_recur ):
583     """Isole le solide de son arboresence
584
585 Entrées :
586   :solide: le solide à traiter
587   :n_recur: numéro de la récurrence
588
589 Sorties :
590   :objet: le solide isolé
591   :recover: la fonction de récupération
592 """
593
594     nom_fonction = __name__ + "/_isole_solide_b"
595     blabla = "Dans {} :".format(nom_fonction)
596     if self._verbose_max:
597       print_tab (n_recur, blabla)
598       texte = "Pour le solide '{}' ".format(solide.name())
599       texte += "de l'objet principal '{}'".format(self.objet_principal.name())
600       print_tab (n_recur, texte)
601
602     if self._verbose_max:
603       print_tab (n_recur, ". Mise en place du solide")
604
605     self.nom_solide_aux = self.objet_principal.name()
606     self.fonction_0 = None
607
608     return solide, None
609
610 #===========================  Fin de la méthode ==================================
611
612 #=========================== Début de la méthode =================================
613
614   def _faces_du_solide ( self, geompy, objet_geom, solide, n_recur=0 ):
615     """Détermine les faces d'un solide
616
617 Entrées :
618   :geompy: environnement de GEOM
619   :objet_geom: l'objet solide à traiter au format GEOM
620   :solide: solide SHAPER à traiter
621   :n_recur: niveau de récursivité
622
623 Sorties :
624   :l_faces_geom: liste des faces du solide au format GEOM
625   :l_faces: liste des faces du solide
626 """
627
628     nom_fonction = __name__ + "/_faces_du_solide"
629     blabla = "Dans {} :".format(nom_fonction)
630     if self._verbose_max:
631       print_tab (n_recur, blabla, saut_av=True)
632
633     erreur = 0
634     message = ""
635     l_faces_geom = list()
636     l_faces = list()
637
638     while ( not erreur ):
639
640       if self._verbose_max:
641         print_tab (n_recur, ".. Traitement du solide ", self.nom_solide)
642         longueur, aire, volume = geompy.BasicProperties(objet_geom)
643         texte = "{}".format(geompy.WhatIs(objet_geom))
644         texte += ". longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
645         print (texte)
646
647 # Liste des faces qui composent le solide
648       l_faces_geom = geompy.ExtractShapes(objet_geom, geompy.ShapeType["FACE"], True)
649       #if self._verbose_max:
650         #print ("Liste des {} faces qui composent le solide :".format(len(l_faces_geom)))
651         #for iaux, face in enumerate(l_faces_geom):
652           #print ("Face n° {} :\n {}".format(iaux,geompy.WhatIs(face)))
653
654       print_tab (n_recur, "Type python : ", type(solide))
655       print_tab (n_recur, "Type ", solide.shapeType())
656       #print ("Type {}".format(solide.shapeTypeStr()))
657       #print ("volume = {}".format(GeomAlgoAPI_ShapeTools.volume(solide)))
658       l_faces = list()
659       #exp = GeomAPI_ShapeExplorer(solide, GeomAPI_Shape.FACE)
660       #while exp.more():
661         #l_faces.append(exp.current().face())
662         #exp.next()
663
664       break
665
666     return erreur, message, l_faces_geom, l_faces
667
668 #===========================  Fin de la méthode ==================================
669
670 #=========================== Début de la méthode =================================
671
672   def _calcul_caract_faces ( self, geompy, l_faces, n_recur ):
673     """Calcule les caractéristiques géométriques des faces
674
675 Entrées :
676   :geompy: environnement de GEOM
677   :l_faces: liste des faces du solide
678   :n_recur: niveau de récursivité
679
680 Sorties :
681   :tb_caract: tableau des caractéristiques géométriques des faces
682 """
683
684     nom_fonction = __name__ + "/_calcul_caract_faces"
685     blabla = "Dans {} :".format(nom_fonction)
686
687     nb_faces = len(l_faces)
688     if self._verbose_max:
689       print_tab (n_recur, blabla, saut_av=True)
690       print_tab (n_recur, "Nombre de faces : ", nb_faces)
691
692     tb_caract = np.zeros((nb_faces,3), dtype = 'object')
693     for iaux, face in enumerate(l_faces):
694       _, aire, _ = geompy.BasicProperties(face)
695       #longueur, aire, volume = geompy.BasicProperties(face)
696       if self._verbose_max:
697         texte = "\t. Face numéro {}".format(iaux)
698         #texte += "\n\t. longueur, aire, volume : {}, {}, {}".format(longueur,aire,volume)
699         texte += ", surface : {}".format(aire)
700         print (texte)
701
702       tb_caract [iaux][0] = face
703       tb_caract [iaux][1] = aire
704       tb_caract [iaux][2] = geompy.KindOfShape(face)
705       if self._verbose_max:
706         print ("\t. tb_caract : {} {}".format(aire,tb_caract[iaux][2]))
707
708     return tb_caract
709
710 #===========================  Fin de la méthode ==================================
711
712 #=========================== Début de la méthode =================================
713
714   def _tri_faces ( self, tb_caract, n_recur ):
715     """Trie les faces en fonction de leurs surfaces
716
717 Entrées :
718   :tb_caract: tableau des caractéristiques géométriques des faces
719   :n_recur: niveau de récursivité
720
721 Sorties :
722   :tb_caract_1[-1], tb_caract_1[-2]: les caractéristiques des 2 faces les plus grandes
723 """
724
725     erreur = 0
726     message = ""
727
728     nom_fonction = __name__ + "/_tri_faces"
729     blabla = "Dans {} :".format(nom_fonction)
730
731 # Tri du tableau en fonction des surfaces
732     if self._verbose_max:
733       print_tab (n_recur, blabla)
734       print_tab (n_recur, "tb_caract brut : ", tb_caract)
735     tb_caract_1 = sorted(tb_caract, key=lambda colonnes: colonnes[1])
736     if self._verbose_max:
737       print_tab (n_recur, "tb_caract trié :", tb_caract_1)
738
739     if self._verbose_max:
740       texte  = "\tSurface de la plus grande face      : {}, de caractéristiques {}\n".format(tb_caract_1[-1][1],tb_caract_1[-1][2])
741       texte += "\tSurface de la face suivante         : {}, de caractéristiques {}".format(tb_caract_1[-2][1],tb_caract_1[-2][2])
742       if self._verbose_max:
743         texte += "\n\tSurface de la 3ème face suivante    : {}, de caractéristiques {}".format(tb_caract_1[-3][1],tb_caract_1[-3][2])
744       print (texte)
745
746 # La surface suivante doit être différente, sinon ce n'est pas un solide mince
747     ecart = np.abs((tb_caract_1[-1][1]-tb_caract_1[-3][1])/tb_caract_1[-1][1])
748     if ( ecart < self._epsilon ):
749       message  = "\nSolide '{}'\n".format(self.nom_solide)
750       message += ". Surface de la plus grande face   : {}\n".format(tb_caract_1[-1][1])
751       message += ". Surface de la 1ère face suivante : {}\n".format(tb_caract_1[-2][1])
752       message += ". Surface de la 2ème face suivante : {}\n".format(tb_caract_1[-3][1])
753       if self._verbose_max:
754         message += ". Ecart relatif :{:4.1f}%\n".format(ecart*100.)
755       message += "L'écart est trop faible par rapport à la limite de {}%.\n".format(self._epsilon*100.)
756       message += "==> Impossible de créer la face médiane car le solide n'est pas assez mince.\n"
757       erreur = -1
758       self.d_statut_so[self.nom_solide] = -1
759       self.faces_pb_nb += 1
760       self.faces_pb_msg += message
761
762     return erreur, message, tb_caract_1[-1], tb_caract_1[-2]
763
764 #===========================  Fin de la méthode ==================================
765
766 #=========================== Début de la méthode =================================
767
768   def _calcul_caract_aretes_face ( self, geompy, caract_face ):
769     """Détermine les caractéristiques des arêtes d'une face
770
771 Entrées :
772   :geompy: environnement de GEOM
773   :caract_face: les caractéristiques de la face
774
775 Sorties :
776   :caract_arete_face: les caractéristiques des arêtes de la face
777 """
778
779     nom_fonction = __name__ + "/_calcul_caract_aretes_face"
780     blabla = "Dans {} :\n".format(nom_fonction)
781
782     if self._verbose_max:
783       texte = blabla
784       texte += "face : {}\n".format(caract_face)
785       print (texte)
786
787 # Détermination des arêtes pour chaque face
788     face = caract_face[0]
789     l_aretes = geompy.ExtractShapes(face, geompy.ShapeType["EDGE"], True)
790     caract_arete_face = list()
791     for arete in l_aretes:
792       caract_arete_face.append(geompy.KindOfShape(arete))
793
794     if self._verbose_max:
795       print ("Aretes de la face : {}".format(caract_arete_face))
796
797     return caract_arete_face
798
799 #===========================  Fin de la méthode ==================================
800
801 #=========================== Début de la méthode =================================
802
803   def _verif_epaisseur ( self, epaisseur ):
804     """Contrôle de la validité de l'épaisseur
805
806 Entrées :
807   :epaisseur: épaisseur du solide
808 """
809
810     nom_fonction = __name__ + "/_verif_epaisseur"
811     blabla = "Dans {} :\n".format(nom_fonction)
812
813     if self._verbose_max:
814       texte = blabla
815       texte += ". Epaisseur du solide : {}\n".format(epaisseur)
816       texte += ". EP_MIN              : {}".format(EP_MIN)
817       print (texte)
818
819     if ( epaisseur <= EP_MIN ):
820       message  = "\nSolide '{}'\n".format(self.nom_solide)
821       message += ". Epaisseur : {}\n".format(epaisseur)
822       message += "L'épaisseur est trop faible par rapport à la limite de {}.\n".format(EP_MIN)
823       message += "==> Impossible de créer la face médiane car le solide est trop mince.\n"
824       erreur = 2
825       self.d_statut_so[self.nom_solide] = 2
826       self.faces_pb_nb += 1
827       self.faces_pb_msg += message
828
829     else:
830       erreur = 0
831     #print ("erreur = {}".format(erreur))
832
833     return erreur
834
835 #===========================  Fin de la méthode ==================================
836
837 #=========================== Début de la méthode =================================
838
839   def _cree_face_mediane ( self, solide, geompy, caract_face_1, caract_face_2, n_recur ):
840     """Crée la face médiane entre deux autres
841
842 Entrées :
843   :solide: solide SHAPER à traiter
844   :geompy: environnement de GEOM
845   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
846   :n_recur: niveau de récursivité
847
848 Sorties :
849   :face: la face médiane créée
850 """
851
852     nom_fonction = __name__ + "/_cree_face_mediane"
853     blabla = "Dans {} :".format(nom_fonction)
854
855     if self._verbose_max:
856       print_tab (n_recur, blabla)
857       print_tab (n_recur, "face_1 : " ,caract_face_1)
858       print_tab (n_recur, "face_2 : " ,caract_face_2)
859
860     erreur = 0
861     face =  None
862
863 # 1. Forme de la face
864     forme = caract_face_1[2][0]
865     if self._verbose_max:
866       print ("forme = {}".format(forme) )
867
868 # 2. Traitement selon la forme de la face
869 # 2.1. Face plane
870     if forme in ( geompy.kind.DISK_CIRCLE, geompy.kind.DISK_ELLIPSE, geompy.kind.POLYGON, geompy.kind.PLANE, geompy.kind.PLANAR ):
871       erreur, face = self._cree_face_mediane_plane ( geompy, solide, caract_face_1, caract_face_2, n_recur )
872
873 # 2.2. Face cylindrique
874     elif forme == geompy.kind.CYLINDER2D:
875       erreur, face = self._cree_face_mediane_cylindre ( solide, caract_face_1, caract_face_2, n_recur )
876
877 # 2.3. Face sphérique
878     elif forme == geompy.kind.SPHERE2D:
879       erreur, face = self._cree_face_mediane_sphere ( caract_face_1, caract_face_2, n_recur )
880
881 # 2.4. Face torique
882     elif forme == geompy.kind.TORUS2D:
883       erreur, face = self._cree_face_mediane_tore ( caract_face_1, caract_face_2, n_recur )
884
885 # 2.5. Face conique
886     elif forme == geompy.kind.CONE2D:
887       erreur, face = self._cree_face_mediane_cone ( geompy, caract_face_1, caract_face_2, n_recur )
888
889 # 2.N. Face de forme inconnue
890     else:
891       message  = "\nSolide '{}'\n".format(self.nom_solide)
892       message += "sa face la plus grande est de forme : {}\n".format(forme)
893       message += "==> Impossible de créer la face médiane.\n"
894       erreur = -2
895       self.d_statut_so[self.nom_solide] = -2
896       self.faces_pb_nb += 1
897       self.faces_pb_msg += message
898
899 # 3. Gestion de la face produite
900
901     if face is not None:
902       self._cree_face_mediane_0 ( face, n_recur )
903
904     return erreur, face
905
906 #===========================  Fin de la méthode ==================================
907
908 #=========================== Début de la méthode =================================
909
910   def _cree_face_mediane_0 ( self, face, n_recur ):
911     """Gestion de la face médiane créée entre deux autres
912
913 Entrées :
914   :face: la face médiane créée
915   :n_recur: niveau de récursivité
916 """
917
918     nom_fonction = __name__ + "/_cree_face_mediane_0"
919     blabla = "Dans {} :".format(nom_fonction)
920
921     if self._verbose_max:
922       print_tab (n_recur, blabla)
923
924 # 1. Nom de la face
925     nom_face = self.nom_solide+"_M"
926     if self._verbose_max:
927       print_tab (n_recur,"Nom de la face créée : ", nom_face)
928     #if ( self.nom_solide_aux != self.objet_principal.name() ):
929       #nom_face += "S"
930     nommage (face, nom_face)
931
932 # 2. Mémorisation de la face et de la fonction initiale
933     self.l_faces_m.append((face, self.fonction_0))
934
935 # 3. Couleur verte pour la face
936     self._couleur_objet (face, coul_r=0, coul_g=170, coul_b=0)
937
938 # 4. Changement de statut pour le solide
939     self.d_statut_so[self.nom_solide] = 1
940
941     return
942
943 #===========================  Fin de la méthode ==================================
944
945 #=========================== Début de la méthode =================================
946
947   def _cree_face_mediane_plane ( self, geompy, solide, caract_face_1, caract_face_2, n_recur ):
948     """Crée la face médiane entre deux autres - cas des surfaces planes
949
950 Entrées :
951   :geompy: environnement de GEOM
952   :solide: l'objet solide à traiter
953   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
954   :n_recur: niveau de récursivité
955
956 Sorties :
957   :face: la face médiane
958 """
959
960     nom_fonction = __name__ + "/_cree_face_mediane_plane"
961     blabla = "Dans {} :".format(nom_fonction)
962     if self._verbose_max:
963       print_tab (n_recur, blabla)
964
965 #   Caractéristiques des surfaces
966     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 )
967
968 #   Contrôle de la validité de l'épaisseur
969     erreur = self._verif_epaisseur ( d_face_1_2 )
970
971 #   Création de la face
972     if not erreur:
973       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 )
974     else:
975       face = None
976
977     return erreur, face
978
979 #===========================  Fin de la méthode ==================================
980
981 #=========================== Début de la méthode =================================
982
983   def _cree_face_mediane_plane_0 ( self, geompy, solide, caract_face_1, caract_face_2, n_recur ):
984     """Crée la face médiane entre deux autres - cas des surfaces planes
985
986 Décodage des caractéristiques
987
988 Entrées :
989   :geompy: environnement de GEOM
990   :solide: l'objet solide à traiter
991   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
992   :n_recur: niveau de récursivité
993
994 Sorties :
995   :coo_x, coo_y, coo_z: coordonnées du centre de la base
996   :vnor_x, vnor_y, vnor_z: coordonnées du vecteur normal
997   :taille: estimation de la taille de la future face
998   :d_face_1_2: la distance entre les deux faces
999 """
1000
1001     nom_fonction = __name__ + "/_cree_face_mediane_plane_0"
1002     blabla = "Dans {} :".format(nom_fonction)
1003
1004     if self._verbose_max:
1005       print_tab (n_recur, blabla)
1006       print_tab (n_recur, "face_1 : ", caract_face_1)
1007       print_tab (n_recur, "face_2 : ", caract_face_2)
1008
1009 # 1. Caractéristiques de la base
1010 #   Coordonnées du centre de la base
1011     coo_x = caract_face_1[2][1]
1012     coo_y = caract_face_1[2][2]
1013     coo_z = caract_face_1[2][3]
1014 #   Coordonnées du vecteur normal
1015     vnor_x = caract_face_1[2][4]
1016     vnor_y = caract_face_1[2][5]
1017     vnor_z = caract_face_1[2][6]
1018 #   taille : la diagonale de la boîte englobante permet d'être certain de tout prendre
1019     l_diag = self._calcul_boite_englobante ( solide, n_recur )
1020     taille = 10.*l_diag
1021     if self._verbose_max:
1022       print_tab (n_recur, "Taille englobante : ",taille)
1023
1024 # 2. Distance entre les deux faces
1025     face_1 = caract_face_1[0]
1026     face_2 = caract_face_2[0]
1027     d_face_1_2 = geompy.MinDistance(face_1, face_2)
1028     if self._verbose_max:
1029       print_tab (n_recur, "Distance entre les deux faces = ", d_face_1_2)
1030
1031     return coo_x, coo_y, coo_z, vnor_x, vnor_y, vnor_z, taille, d_face_1_2
1032
1033 #===========================  Fin de la méthode ==================================
1034
1035 #=========================== Début de la méthode =================================
1036
1037   def _cree_face_mediane_plane_1 ( self, solide, coo_c, vnor, taille, d_face_1_2, n_recur ):
1038     """Crée la face médiane entre deux autres - cas des surfaces planes
1039
1040 Création des objets temporaires et de la face médiane
1041
1042 Entrées :
1043   :solide: l'objet solide à traiter
1044   :coo_c: coordonnées du centre de la base
1045   :vnor: coordonnées du vecteur normal
1046   :taille: estimation de la taille de la future face
1047   :d_face_1_2: la distance entre les deux faces
1048   :n_recur: niveau de récursivité
1049
1050 Sorties :
1051   :face: la face médiane
1052 """
1053
1054     nom_fonction = __name__ + "/_cree_face_mediane_plane_1"
1055     blabla = "Dans {} :".format(nom_fonction)
1056     if self._verbose_max:
1057       print_tab (n_recur, blabla)
1058       print_tab (n_recur, "Centre   : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1059       print_tab (n_recur, "Normale  : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
1060       print_tab (n_recur, "Taille   : ", taille)
1061       print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1062
1063 # 1. Objets préalables
1064     nom_par_1 = "{}_taille".format(self.nom_solide)
1065     model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(taille))
1066
1067     centre, v_norm, plan = self._cree_centre_axe_plan ( coo_c, vnor, self.nom_solide, n_recur )
1068
1069 # 2. Création de l'esquisse
1070     sketch = self._cree_face_mediane_plane_1_a ( plan, centre, nom_par_1, taille, n_recur )
1071
1072 # 3. La face
1073     face = self._cree_face_mediane_plane_1_b ( solide, sketch, v_norm, d_face_1_2, n_recur )
1074
1075     print ("fin de {}".format(nom_fonction))
1076
1077     return face
1078
1079 #===========================  Fin de la méthode ==================================
1080
1081 #=========================== Début de la méthode =================================
1082
1083   def _cree_face_mediane_plane_1_a ( self, plan, centre, nom_par_1, taille, n_recur ):
1084     """Crée la face médiane entre deux autres - cas des surfaces planes - l'esquisse
1085
1086 Entrées :
1087   :plan: plan
1088   :centre: centre
1089   :nom_par_1: nom du paramètre
1090   :taille: estimation de la taille de la future face
1091   :n_recur: niveau de récursivité
1092
1093 Sorties :
1094   :sketch: l'esquisse
1095 """
1096
1097     nom_fonction = __name__ + "/_cree_face_mediane_plane_1_a"
1098     blabla = "Dans {} :".format(nom_fonction)
1099     if self._verbose_max:
1100       print_tab (n_recur, blabla)
1101       print_tab (n_recur, "Plan      : {}".format(plan.name()))
1102       print_tab (n_recur, "Centre    : {}".format(centre.name()))
1103       print_tab (n_recur, "Paramètre : {}".format(nom_par_1))
1104       print_tab (n_recur, "taille    : {}".format(taille))
1105
1106     sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1107
1108     ### Create SketchLine
1109     SketchLine_1 = sketch.addLine(-taille/2., taille/2., taille/2., taille/2.)
1110     sketch.setHorizontal(SketchLine_1.result())
1111
1112     ### Create SketchLine
1113     SketchLine_2 = sketch.addLine(taille/2., taille/2., taille/2., -taille/2.)
1114     sketch.setVertical(SketchLine_2.result())
1115     sketch.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
1116
1117     ### Create SketchLine
1118     SketchLine_3 = sketch.addLine(taille/2., -taille/2., -taille/2., -taille/2.)
1119     sketch.setHorizontal(SketchLine_3.result())
1120     sketch.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
1121     sketch.setLength(SketchLine_3.result(), nom_par_1)
1122
1123     ### Create SketchLine
1124     SketchLine_4 = sketch.addLine(-taille/2., -taille/2., -taille/2., taille/2.)
1125     sketch.setVertical(SketchLine_4.result())
1126     sketch.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
1127     sketch.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
1128     sketch.setEqual(SketchLine_3.result(), SketchLine_4.result())
1129
1130     SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", centre.name()), False)
1131     SketchPoint_1 = SketchProjection_1.createdFeature()
1132
1133     ### Create SketchLine
1134     SketchLine_5 = sketch.addLine(-taille/2., taille/2., taille/2., -taille/2.)
1135     SketchLine_5.setAuxiliary(True)
1136     sketch.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
1137     sketch.setCoincident(SketchLine_3.startPoint(), SketchLine_5.endPoint())
1138     sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_5.result())
1139
1140     ### Create SketchLine
1141     SketchLine_6 = sketch.addLine(taille/2., taille/2., -taille/2., -taille/2.)
1142     SketchLine_6.setAuxiliary(True)
1143     sketch.setCoincident(SketchLine_2.startPoint(), SketchLine_6.startPoint())
1144     sketch.setCoincident(SketchLine_4.startPoint(), SketchLine_6.endPoint())
1145     sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_6.result())
1146
1147     model.do()
1148
1149     nom_sketch = "{}_esquisse".format(self.nom_solide)
1150     nommage (sketch, nom_sketch)
1151
1152     print ("fin de {}".format(nom_fonction))
1153
1154     return sketch
1155
1156 #===========================  Fin de la méthode ==================================
1157
1158 #=========================== Début de la méthode =================================
1159
1160   def _cree_face_mediane_plane_1_b ( self, solide, sketch, v_norm, d_face_1_2, n_recur ):
1161     """Crée la face médiane entre deux autres - cas des surfaces planes
1162
1163 Création de la face médiane
1164
1165 Entrées :
1166   :solide: l'objet solide à traiter
1167   :sketch: l'esquisse
1168   :v_norm: vecteur normal
1169   :d_face_1_2: la distance entre les deux faces
1170   :n_recur: niveau de récursivité
1171
1172 Sorties :
1173   :face: la face médiane
1174 """
1175
1176     nom_fonction = __name__ + "/_cree_face_mediane_plane_1_b"
1177     blabla = "Dans {} :".format(nom_fonction)
1178     if self._verbose_max:
1179       print_tab (n_recur, blabla)
1180       print_tab (n_recur, "Esquisse : ", sketch.name())
1181       print_tab (n_recur, "Distance entre les deux faces : ", d_face_1_2)
1182
1183     ### Create LinearCopy
1184     LinearCopy_1 = model.addMultiTranslation(self.part_doc, [model.selection("SOLID", self.nom_solide_aux)], model.selection("EDGE", "PartSet/OX"), 0, 1, keepSubResults = True)
1185     nom = "{}_0".format(self.nom_solide_aux)
1186     nommage (LinearCopy_1, nom)
1187
1188     ### Create Recover
1189     Recover_1 = model.addRecover(self.part_doc, LinearCopy_1, [solide])
1190     nom = "{}_1".format(self.nom_solide_aux)
1191     nommage (Recover_1, nom)
1192
1193     # Création d'une face ; on la translate d'une demi-épaisseur.
1194     for iaux in range(2):
1195
1196       distance = -0.5*d_face_1_2*float(2*iaux-1)
1197       nom_solide = "{}_{}".format(self.nom_solide_aux,iaux)
1198       face = self._cree_face_mediane_plane_2 ( sketch.name(), v_norm.name(), nom_solide, distance, iaux, n_recur )
1199
1200       if face.results():
1201         face = self._cree_face_mediane_plane_11 ( face, Recover_1, n_recur )
1202         break
1203       # Si l'intersection est vide, on la translate dans l'autre sens
1204       else:
1205         if self._verbose_max:
1206           print_tab (n_recur, "L'intersection est vide.")
1207         face = None
1208
1209     print ("fin de {}".format(nom_fonction))
1210
1211     return face
1212
1213 #===========================  Fin de la méthode ==================================
1214
1215 #=========================== Début de la méthode =================================
1216
1217   def _cree_face_mediane_plane_11 ( self, face, Recover_1, n_recur ):
1218     """Crée la face médiane entre deux autres - cas des surfaces planes
1219
1220 Création des objets temporaires et de la face médiane
1221
1222 Entrées :
1223   :face: la face médiane
1224   :Recover_1: la récupératiuon du solide
1225   :n_recur: niveau de récursivité
1226
1227 Sorties :
1228   :face: la face médiane
1229 """
1230
1231     nom_fonction = __name__ + "/_cree_face_mediane_plane_11"
1232     blabla = "Dans {} :".format(nom_fonction)
1233     if self._verbose_max:
1234       print_tab (n_recur, blabla)
1235       print_tab (n_recur, "face : ", face.name())
1236
1237     # Si on traite un objet solide unique, on le récupère
1238     if ( self.nom_solide_aux == self.objet_principal.name() ):
1239       if self._verbose_max:
1240         print_tab (n_recur, "On traite un objet solide unique ==> on le récupère.")
1241       Recover_2 = model.addRecover(self.part_doc, face, [Recover_1.result()])
1242       Recover_2.result().setName("{}_S".format(self.nom_solide_aux))
1243
1244     nb_inter = face.result().numberOfSubs()
1245     if self._verbose_max:
1246       print_tab (n_recur, "Nombre d'intersections : ", nb_inter)
1247
1248     if (nb_inter > 1 ):
1249       face = self._cree_face_mediane_plane_3 ( face )
1250
1251     return face
1252
1253 #===========================  Fin de la méthode ==================================
1254
1255 #=========================== Début de la méthode =================================
1256
1257   def _cree_face_mediane_plane_2 ( self, nom_sketch, nom_normal, nom_solide, distance, icpt, n_recur ):
1258     """Crée la face médiane entre deux autres - cas des surfaces planes
1259
1260 Intersection de la face avec le solide
1261
1262 Entrées :
1263   :nom_sketch: nom de l'esquisse
1264   :nom_normal: nom du vecteur normal
1265   :nom_solide: nom du solide à intersecter
1266   :distance: la distance de translation
1267   :icpt: numéro de la tentative
1268
1269 Sorties :
1270   :face: la face médiane
1271 """
1272
1273     nom_fonction = __name__ + "/_cree_face_mediane_plane_2"
1274     blabla = "Dans {} :\n".format(nom_fonction)
1275     if self._verbose_max:
1276       print_tab (n_recur, blabla)
1277       print_tab (n_recur, "nom_sketch : ", nom_sketch)
1278       print_tab (n_recur, "nom_normal : ", nom_normal)
1279       print_tab (n_recur, "nom_solide : ", nom_solide)
1280       print_tab (n_recur, "distance   : ", distance)
1281
1282     # Création d'une face
1283     Face_1 = model.addFace(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(nom_sketch))])
1284     nom_face_1 = "{}_face_1_{}".format(self.nom_solide_aux,icpt)
1285     nommage (Face_1, nom_face_1)
1286
1287 #   On la translate
1288     Translation_1 = model.addTranslation(self.part_doc, [model.selection("FACE", nom_face_1)], axis = model.selection("EDGE", nom_normal), distance = distance, keepSubResults = True)
1289     nom_trans = "{}_trans_{}".format(self.nom_solide_aux,icpt)
1290     nommage (Translation_1, nom_trans)
1291     Translation_1.result().setColor(85, 0, 255)
1292
1293 #   Intersection de cette face avec le solide initial
1294     face = model.addCommon(self.part_doc, [model.selection("SOLID", nom_solide), model.selection("FACE", nom_trans)], keepSubResults = True)
1295
1296     return face
1297
1298 #===========================  Fin de la méthode ==================================
1299
1300 #=========================== Début de la méthode =================================
1301
1302   def _cree_face_mediane_plane_3 ( self, face ):
1303     """Crée la face médiane entre deux autres - cas des surfaces planes
1304
1305 Fusion des 2 intersections
1306
1307 Entrées :
1308   :face: la face médiane composée de plusieurs intersections
1309
1310 Sorties :
1311   :face_m: la face médiane
1312 """
1313
1314     nom_fonction = __name__ + "/_cree_face_mediane_plane_3"
1315     blabla = "Dans {} :\n".format(nom_fonction)
1316     if self._verbose_max:
1317       texte = blabla
1318       print (texte)
1319
1320 # Nommage des sous-objets
1321     l_fuse = list()
1322     for iaux in range(face.result().numberOfSubs()):
1323       nom = "{}_common_{}".format(self.nom_solide_aux,iaux)
1324       face.result().subResult(iaux).setName(nom)
1325       l_fuse.append(model.selection("FACE", '{}'.format(nom)))
1326
1327 #   Fusion
1328     if self._verbose_max:
1329       print ("Fusion de {} faces.".format(len(l_fuse)))
1330     face_m = model.addFuse(self.part_doc, l_fuse, keepSubResults = True)
1331
1332     return face_m
1333
1334 #===========================  Fin de la méthode ==================================
1335
1336 #=========================== Début de la méthode =================================
1337
1338   def _cree_face_mediane_cylindre ( self, solide, caract_face_1, caract_face_2, n_recur ):
1339     """Crée la face médiane entre deux autres - cas des cylindres
1340
1341 Entrées :
1342   :solide: solide SHAPER à traiter
1343   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1344   :n_recur: niveau de récursivité
1345
1346 Sorties :
1347   :face: la face médiane
1348 """
1349
1350     nom_fonction = __name__ + "/_cree_face_mediane_cylindre"
1351     blabla = "Dans {} :".format(nom_fonction)
1352
1353 #   Les deux faces
1354     if self._verbose_max:
1355       print_tab (n_recur, blabla)
1356       print_tab (n_recur, "face_1 : ", caract_face_1)
1357       print_tab (n_recur, "face_2 : ", caract_face_2)
1358
1359 #   Caractéristiques des cylindres
1360     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 )
1361
1362 #   Contrôle de la validité de l'épaisseur
1363     erreur = self._verif_epaisseur ( epaisseur )
1364
1365 #   Création de la face
1366     if not erreur:
1367       face = self._cree_face_mediane_cylindre_1 ( (coo_x, coo_y, coo_z), (axe_x, axe_y, axe_z), rayon, hauteur, n_recur )
1368     else:
1369       self._couleur_objet (solide, n_recur, coul_r=0, coul_g=0, coul_b=255)
1370       face = None
1371
1372     return erreur, face
1373
1374 #===========================  Fin de la méthode ==================================
1375
1376 #=========================== Début de la méthode =================================
1377
1378   def _cree_face_mediane_cylindre_0 ( self, solide, caract_face_1, caract_face_2, n_recur ):
1379     """Crée la face médiane entre deux autres - cas des cylindres
1380
1381 Décodage des caractéristiques
1382
1383 Entrées :
1384   :solide: l'objet solide à traiter
1385   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1386   :n_recur: niveau de récursivité
1387
1388 Sorties :
1389   :coo_x, coo_y, coo_z: coordonnées du centre de la base
1390   :axe_x, axe_y, axe_z: coordonnées de l'axe
1391   :rayon: rayon moyen entre les deux faces
1392   :hauteur: hauteur du cylindre
1393   :epaisseur: épaisseur de l'interface entre les deux faces
1394 """
1395
1396     nom_fonction = __name__ + "/_cree_face_mediane_cylindre_0"
1397     blabla = "Dans {} :".format(nom_fonction)
1398
1399     if self._verbose_max:
1400       print_tab (n_recur, blabla)
1401       print_tab (n_recur, "face_1 : ", caract_face_1)
1402       print_tab (n_recur, "face_2 : ", caract_face_2)
1403
1404 #   Coordonnées du centre de la base
1405     coo_x = caract_face_1[2][1]
1406     coo_y = caract_face_1[2][2]
1407     coo_z = caract_face_1[2][3]
1408 #   Coordonnées de l'axe
1409     axe_x = caract_face_1[2][4]
1410     axe_y = caract_face_1[2][5]
1411     axe_z = caract_face_1[2][6]
1412 #   Rayons
1413     rayon = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1414 #   Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
1415     l_diag = self._calcul_boite_englobante ( solide, n_recur )
1416     hauteur = 10.*l_diag
1417     if self._verbose_max:
1418       print_tab (n_recur, "Hauteur englobante : ", hauteur)
1419 #   Epaisseur
1420     epaisseur = np.abs(caract_face_2[2][7]-caract_face_1[2][7])
1421
1422     return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon, hauteur, epaisseur
1423
1424 #===========================  Fin de la méthode ==================================
1425
1426 #=========================== Début de la méthode =================================
1427
1428   def _cree_face_mediane_cylindre_1 ( self, coo_c, v_axe, rayon, hauteur, n_recur ):
1429     """Crée la face médiane entre deux autres - cas des cylindres
1430
1431 Création des objets temporaires et de la face externe du cylindre support
1432
1433 Entrées :
1434   :coo_x, coo_y, coo_z: coordonnées du centre de la base
1435   :axe_x, axe_y, axe_z: coordonnées de l'axe
1436   :rayon: rayon moyen entre les deux faces
1437   :hauteur: hauteur du cylindre
1438   :n_recur: niveau de récursivité
1439
1440 Sorties :
1441   :face: la face médiane
1442 """
1443     nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1"
1444     blabla = "Dans {} :\n".format(nom_fonction)
1445
1446 #   Les caractéristiques du cylindre à créer
1447     if self._verbose_max:
1448       print_tab (n_recur, blabla)
1449       print_tab (n_recur, "Centre  : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
1450       print_tab (n_recur, "Axe     : ({}, {}, {})".format(v_axe[0], v_axe[1], v_axe[2]))
1451       print_tab (n_recur, "Rayon   : ", rayon)
1452       print_tab (n_recur, "Hauteur : ", hauteur)
1453
1454 # 1. Objets préalables
1455     nom_par_1 = "{}_R".format(self.nom_solide)
1456     model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1457     nom_par_2 = "{}_H".format(self.nom_solide)
1458     model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(hauteur))
1459
1460     centre, axe, plan = self._cree_centre_axe_plan ( coo_c, v_axe, self.nom_solide, n_recur )
1461
1462 # 2. Création de l'esquisse
1463     sketch = self._cree_face_mediane_cylindre_1_a ( plan, centre, rayon, nom_par_1, n_recur )
1464
1465 # 3. La face
1466     face = self._cree_face_mediane_cylindre_1_b ( sketch, nom_par_2, n_recur )
1467
1468     return face
1469
1470 #===========================  Fin de la méthode ==================================
1471
1472 #=========================== Début de la méthode =================================
1473
1474   def _cree_face_mediane_cylindre_1_a ( self, plan, centre, rayon, nom_par_1, n_recur ):
1475     """Crée la face médiane entre deux autres - cas des cylindres
1476
1477 Création des objets temporaires et de la face externe du cylindre support
1478
1479 Entrées :
1480   :coo_x, coo_y, coo_z: coordonnées du centre de la base
1481   :axe_x, axe_y, axe_z: coordonnées de l'axe
1482   :rayon: rayon moyen entre les deux faces
1483   :nom_par_1: nom_par_1
1484   :n_recur: niveau de récursivité
1485
1486 Sorties :
1487   :face: la face médiane
1488 """
1489     nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1_a"
1490     blabla = "Dans {} :\n".format(nom_fonction)
1491
1492 #   Les caractéristiques du cylindre à créer
1493     if self._verbose_max:
1494       print_tab (n_recur, blabla)
1495       print_tab (n_recur, "Plan      : {}".format(plan.name()))
1496       print_tab (n_recur, "Centre    : {}".format(centre.name()))
1497       print_tab (n_recur, "Rayon   : ", rayon)
1498
1499     sketch = model.addSketch(self.part_doc, model.selection("FACE", plan.name()))
1500
1501     SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", centre.name()), False)
1502     SketchPoint_1 = SketchProjection_1.createdFeature()
1503
1504     SketchCircle_1 = sketch.addCircle(0., 0., rayon)
1505     sketch.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
1506     sketch.setRadius(SketchCircle_1.results()[1], nom_par_1)
1507     model.do()
1508
1509     nom_sketch = "{}_esquisse".format(self.nom_solide)
1510     nommage (sketch, nom_sketch)
1511
1512     return sketch
1513
1514 #===========================  Fin de la méthode ==================================
1515
1516 #=========================== Début de la méthode =================================
1517
1518   def _cree_face_mediane_cylindre_1_b ( self, sketch, nom_par_2, n_recur ):
1519     """Crée la face médiane entre deux autres - cas des cylindres
1520
1521 Création des objets temporaires et de la face externe du cylindre support
1522
1523 Entrées :
1524   :sketch: l'esquisse
1525   :n_recur: niveau de récursivité
1526
1527 Sorties :
1528   :face: la face médiane
1529 """
1530     nom_fonction = __name__ + "/_cree_face_mediane_cylindre_1_b"
1531     blabla = "Dans {} :\n".format(nom_fonction)
1532
1533 #   Les caractéristiques du cylindre à créer
1534     if self._verbose_max:
1535       print_tab (n_recur, blabla)
1536       print_tab (n_recur, "Esquisse : ", sketch.name())
1537       print_tab (n_recur, "nom_par_2 : ", nom_par_2)
1538
1539 #   Création du cylindre complet
1540     cylindre = model.addExtrusion(self.part_doc, [model.selection("COMPOUND", "all-in-{}".format(sketch.name()))], model.selection(), nom_par_2, nom_par_2, "Edges")
1541
1542     nom_cylindre = "{}_cylindre".format(self.nom_solide)
1543     nommage (cylindre, nom_cylindre, (85, 0, 255))
1544
1545 #   Intersection de la face cylindrique avec le solide initial
1546     face = self._creation_face_inter ( nom_cylindre )
1547
1548     return face
1549
1550 #===========================  Fin de la méthode ==================================
1551
1552 #=========================== Début de la méthode =================================
1553
1554   def _cree_face_mediane_sphere ( self, caract_face_1, caract_face_2, n_recur ):
1555     """Crée la face médiane entre deux autres - cas des sphères
1556
1557 Entrées :
1558   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1559   :n_recur: niveau de récursivité
1560
1561 Sorties :
1562   :face: la face médiane
1563 """
1564
1565     nom_fonction = __name__ + "/_cree_face_mediane_sphere"
1566     blabla = "Dans {} :".format(nom_fonction)
1567
1568 #   Les deux faces
1569     if self._verbose_max:
1570       print_tab (n_recur, blabla)
1571       print_tab (n_recur, "face_1 : ", caract_face_1)
1572       print_tab (n_recur, "face_2 : ", caract_face_2)
1573
1574 #   Caractéristiques des sphères
1575     coo_x, coo_y, coo_z, rayon, epaisseur = self._cree_face_mediane_sphere_0 ( caract_face_1, caract_face_2, n_recur )
1576
1577 #   Contrôle de la validité de l'épaisseur
1578     erreur = self._verif_epaisseur ( epaisseur )
1579
1580 #   Création de la face
1581     if not erreur:
1582       face = self._cree_face_mediane_sphere_1 ( coo_x, coo_y, coo_z, rayon )
1583     else:
1584       face = None
1585
1586     return erreur, face
1587
1588 #===========================  Fin de la méthode ==================================
1589
1590 #=========================== Début de la méthode =================================
1591
1592   def _cree_face_mediane_sphere_0 ( self, caract_face_1, caract_face_2, n_recur ):
1593     """Crée la face médiane entre deux autres - cas des sphères
1594
1595 Décodage des caractéristiques
1596
1597 Entrées :
1598   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1599   :n_recur: niveau de récursivité
1600
1601 Sorties :
1602   :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1603   :rayon: rayon moyen entre les deux faces
1604   :epaisseur: épaisseur de l'interface entre les deux faces
1605 """
1606
1607     nom_fonction = __name__ + "/_cree_face_mediane_sphere_0"
1608     blabla = "Dans {} :".format(nom_fonction)
1609
1610 #   Les deux faces
1611     if self._verbose_max:
1612       print_tab (n_recur, blabla)
1613       print_tab (n_recur, "face_1 : ", caract_face_1)
1614       print_tab (n_recur, "face_2 : ", caract_face_2)
1615
1616 #   Coordonnées du centre de la sphère
1617     coo_x = caract_face_1[2][1]
1618     coo_y = caract_face_1[2][2]
1619     coo_z = caract_face_1[2][3]
1620 #   Rayons
1621     rayon = (caract_face_2[2][4]+caract_face_1[2][4])/2.
1622 #   Epaisseur
1623     epaisseur = np.abs(caract_face_2[2][4]-caract_face_1[2][4])
1624
1625     return coo_x, coo_y, coo_z, rayon, epaisseur
1626
1627 #===========================  Fin de la méthode ==================================
1628
1629 #=========================== Début de la méthode =================================
1630
1631   def _cree_face_mediane_sphere_1 ( self, coo_x, coo_y, coo_z, rayon ):
1632     """Crée la face médiane entre deux autres - cas des sphères
1633
1634 Création des objets temporaires et de la face externe de la sphère support
1635
1636 Entrées :
1637   :coo_x, coo_y, coo_z: coordonnées du centre de la sphère
1638   :rayon: rayon moyen entre les deux faces
1639
1640 Sorties :
1641   :face: la face externe de la sphère support
1642 """
1643
1644     nom_fonction = __name__ + "/_cree_face_mediane_sphere_1"
1645     blabla = "Dans {} :\n".format(nom_fonction)
1646
1647 #   Les caractéristiques de la sphère à créer
1648     if self._verbose_max:
1649       texte = blabla
1650       texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1651       texte += "Rayon : {}".format(rayon)
1652       print (texte)
1653
1654 #   Création du point central
1655     centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1656     nom_centre = "{}_centre".format(self.nom_solide)
1657     centre.result().setName(nom_centre)
1658
1659 #   Création d'un plan passant par ce centre et cet axe
1660     plan = model.addPlane(self.part_doc, model.selection("EDGE", "PartSet/OX"), model.selection("VERTEX", nom_centre), False)
1661     nom_plan = "{}_plan".format(self.nom_solide)
1662     plan.result().setName(nom_plan)
1663
1664 #   Création de l'esquisse
1665     nom_par_1 = "{}_R".format(self.nom_solide)
1666     model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon))
1667
1668     sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1669
1670     SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1671     SketchPoint_1 = SketchProjection_1.createdFeature()
1672
1673     ### Create SketchArc
1674     SketchArc_1 = sketch.addArc(coo_x, coo_y, coo_x-rayon, coo_y, coo_x+rayon, coo_y, False)
1675     sketch.setRadius(SketchArc_1.results()[1], nom_par_1)
1676     sketch.setCoincident(SketchPoint_1.result(), SketchArc_1.center())
1677
1678     ### Create SketchLine
1679     SketchLine_1 = sketch.addLine(coo_x-rayon, coo_y, coo_x+rayon, coo_y)
1680     nom_ligne = "{}_ligne".format(self.nom_solide)
1681     SketchLine_1.setName(nom_ligne)
1682     SketchLine_1.result().setName(nom_ligne)
1683     SketchLine_1.setAuxiliary(True)
1684     sketch.setHorizontal(SketchLine_1.result())
1685     sketch.setCoincident(SketchArc_1.startPoint(), SketchLine_1.startPoint())
1686     sketch.setCoincident(SketchArc_1.endPoint(), SketchLine_1.endPoint())
1687     sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result())
1688
1689     model.do()
1690     nom_sketch = "{}_esquisse".format(self.nom_solide)
1691     sketch.setName(nom_sketch)
1692     sketch.result().setName(nom_sketch)
1693
1694 #   Création de la sphère complète
1695     sphere = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", "{}/{}".format(nom_sketch,nom_ligne)), 360, 0, "Edges")
1696
1697     nom_sphere = "{}_sphere".format(self.nom_solide)
1698     nommage (sphere, nom_sphere, (85, 0, 255))
1699
1700 #   Intersection de la face sphérique avec le solide initial
1701     face = self._creation_face_inter ( nom_sphere )
1702
1703     return face
1704
1705 #===========================  Fin de la méthode ==================================
1706
1707 #=========================== Début de la méthode =================================
1708
1709   def _cree_face_mediane_tore ( self, caract_face_1, caract_face_2, n_recur ):
1710     """Crée la face médiane entre deux autres - cas des tores
1711
1712 Entrées :
1713   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1714   :n_recur: niveau de récursivité
1715
1716 Sorties :
1717   :face: la face médiane
1718 """
1719
1720     nom_fonction = __name__ + "/_cree_face_mediane_tore"
1721     blabla = "Dans {} :".format(nom_fonction)
1722
1723 #   Les deux faces
1724     if self._verbose_max:
1725       print_tab (n_recur, blabla)
1726       print_tab (n_recur, "face_1 : ", caract_face_1)
1727       print_tab (n_recur, "face_2 : ", caract_face_2)
1728
1729 #   Caractéristiques des tores
1730     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 )
1731
1732 #   Contrôle de la validité de l'épaisseur (bidon)
1733     erreur = self._verif_epaisseur ( EP_MIN*10. )
1734
1735 #   Création de la face
1736     if not erreur:
1737       face = self._cree_face_mediane_tore_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 )
1738     else:
1739       face = None
1740
1741     return erreur, face
1742
1743 #===========================  Fin de la méthode ==================================
1744
1745 #=========================== Début de la méthode =================================
1746
1747   def _cree_face_mediane_tore_0 ( self, caract_face_1, caract_face_2, n_recur ):
1748     """Crée la face médiane entre deux autres - cas des tores
1749
1750 Décodage des caractéristiques
1751
1752 Entrées :
1753   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1754   :n_recur: niveau de récursivité
1755
1756 Sorties :
1757   :coo_x, coo_y, coo_z: coordonnées du centre du tore
1758   :axe_x, axe_y, axe_z: coordonnées de l'axe
1759   :rayon_1 : rayon principal
1760   :rayon_2 : rayon secondaire
1761 """
1762
1763     nom_fonction = __name__ + "/_cree_face_mediane_tore_0"
1764     blabla = "Dans {} :".format(nom_fonction)
1765
1766 #   Les deux faces
1767     if self._verbose_max:
1768       print_tab (n_recur, blabla)
1769       print_tab (n_recur, "face_1 : ", caract_face_1)
1770       print_tab (n_recur, "face_2 : ", caract_face_2)
1771
1772 #   Coordonnées du centre du tore
1773     coo_x = caract_face_1[2][1]
1774     coo_y = caract_face_1[2][2]
1775     coo_z = caract_face_1[2][3]
1776 #   Coordonnées de l'axe
1777     axe_x = caract_face_1[2][4]
1778     axe_y = caract_face_1[2][5]
1779     axe_z = caract_face_1[2][6]
1780 #   Rayons
1781     rayon_1 = caract_face_2[2][7]
1782     rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1783
1784     return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2
1785
1786 #===========================  Fin de la méthode ==================================
1787
1788 #=========================== Début de la méthode =================================
1789
1790   def _cree_face_mediane_tore_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2 ):
1791     """Crée la face médiane entre deux autres - cas des tores
1792
1793 Création des objets temporaires et de la face externe du tore support
1794
1795 Entrées :
1796   :coo_x, coo_y, coo_z: coordonnées du centre du tore
1797   :axe_x, axe_y, axe_z: coordonnées de l'axe
1798   :rayon_1 : rayon principal
1799   :rayon_2 : rayon secondaire
1800
1801 Sorties :
1802   :face: la face externe du tore support
1803 """
1804
1805     nom_fonction = __name__ + "/_cree_face_mediane_tore_1"
1806     blabla = "Dans {} :\n".format(nom_fonction)
1807
1808 #   Les deux faces
1809     if self._verbose_max:
1810       texte = blabla
1811       texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
1812       texte += "Axe    : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
1813       texte += "Rayon principal : {}\n".format(rayon_1)
1814       texte += "Rayon secondaire : {}".format(rayon_2)
1815       print (texte)
1816
1817 #   Création du point central
1818     centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
1819     nom_centre = "{}_centre".format(self.nom_solide)
1820     centre.result().setName(nom_centre)
1821
1822 #   Création de l'axe
1823     axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
1824     nom_axe = "{}_axe".format(self.nom_solide)
1825     axe.result().setName(nom_axe)
1826
1827 #   Création d'un plan passant par ce centre et cet axe
1828     plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
1829     nom_plan = "{}_plan".format(self.nom_solide)
1830     plan.result().setName(nom_plan)
1831
1832 #   Création de l'esquisse
1833     nom_par_1 = "{}_R_1".format(self.nom_solide)
1834     model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
1835     nom_par_2 = "{}_R_2".format(self.nom_solide)
1836     model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
1837
1838     sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
1839
1840     SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
1841     SketchPoint_1 = SketchProjection_1.createdFeature()
1842
1843     SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
1844     SketchLine_1 = SketchProjection_2.createdFeature()
1845
1846     SketchPoint_2 = sketch.addPoint(rayon_1, 0.)
1847     sketch.setDistance(SketchPoint_1.result(), SketchPoint_2.coordinates(), nom_par_1, True)
1848
1849     SketchLine_2 = sketch.addLine(0., 0., rayon_1, 0.)
1850     SketchLine_2.setAuxiliary(True)
1851     sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
1852     sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_2.endPoint())
1853     sketch.setPerpendicular(SketchLine_1.result(), SketchLine_2.result())
1854
1855     SketchCircle_1 = sketch.addCircle(0., 0., rayon_2)
1856     sketch.setCoincident(SketchPoint_2.result(), SketchCircle_1.center())
1857     sketch.setRadius(SketchCircle_1.results()[1], nom_par_2)
1858
1859     model.do()
1860     nom_sketch = "{}_esquisse".format(self.nom_solide)
1861     sketch.setName(nom_sketch)
1862     sketch.result().setName(nom_sketch)
1863
1864 #   Création du tore complet
1865     nom_tore = "{}_tore".format(self.nom_solide)
1866     self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_tore )
1867
1868 #   Intersection de la face torique avec le solide initial
1869     face = self._creation_face_inter ( nom_tore )
1870
1871     return face
1872
1873 #===========================  Fin de la méthode ==================================
1874
1875 #=========================== Début de la méthode =================================
1876
1877   def _cree_face_mediane_cone ( self, geompy, caract_face_1, caract_face_2, n_recur ):
1878     """Crée la face médiane entre deux autres - cas des cones
1879
1880 Entrées :
1881   :geompy: environnement de GEOM
1882   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1883   :n_recur: niveau de récursivité
1884
1885 Sorties :
1886   :face: la face médiane
1887 """
1888
1889     nom_fonction = __name__ + "/_cree_face_mediane_cone"
1890     blabla = "Dans {} :".format(nom_fonction)
1891
1892 #   Les deux faces
1893     if self._verbose_max:
1894       print_tab (n_recur, blabla)
1895       print_tab (n_recur, "face_1 : ", caract_face_1)
1896       print_tab (n_recur, "face_2 : ", caract_face_2)
1897
1898 #   Caractéristiques des cones
1899     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, n_recur )
1900
1901 #   Contrôle de la validité de l'épaisseur (bidon)
1902     erreur = self._verif_epaisseur ( EP_MIN*10. )
1903
1904 #   Création de la face
1905     if not erreur:
1906       face = self._cree_face_mediane_cone_1 ( coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur )
1907     else:
1908       face = None
1909
1910     return erreur, face
1911
1912 #===========================  Fin de la méthode ==================================
1913
1914 #=========================== Début de la méthode =================================
1915
1916   def _cree_face_mediane_cone_0 ( self, geompy, caract_face_1, caract_face_2, n_recur ):
1917     """Crée la face médiane entre deux autres - cas des cones
1918
1919 Décodage des caractéristiques
1920
1921 Entrées :
1922   :geompy: environnement de GEOM
1923   :caract_face_1, caract_face_2: les caractéristiques des 2 faces les plus grandes
1924   :n_recur: niveau de récursivité
1925
1926 Sorties :
1927   :coo_x, coo_y, coo_z: coordonnées du centre de la base
1928   :axe_x, axe_y, axe_z: coordonnées de l'axe
1929   :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1930   :hauteur: hauteur du cone
1931 """
1932
1933     nom_fonction = __name__ + "/_cree_face_mediane_cone_0"
1934     blabla = "Dans {} :".format(nom_fonction)
1935
1936 #   Les deux faces
1937     if self._verbose_max:
1938       print_tab (n_recur, blabla)
1939       print_tab (n_recur, "face_1 : ", caract_face_1)
1940       print_tab (n_recur, "face_2 : ", caract_face_2)
1941
1942 #   Coordonnées du centre de la base
1943     coo_x = caract_face_1[2][1]
1944     coo_y = caract_face_1[2][2]
1945     coo_z = caract_face_1[2][3]
1946 #   Coordonnées de l'axe
1947     axe_x = caract_face_1[2][4]
1948     axe_y = caract_face_1[2][5]
1949     axe_z = caract_face_1[2][6]
1950 #   Rayons
1951 #   Pour un cone complet, les caractéristiques fournies par GEOM sont correctes
1952 #   Mais s'il est découpé, malheureusement,bug dans GEOM et caract_face_2[2][8] est toujours nul !
1953 #   Alors on passe par le décodage des arêtes
1954     #rayon_1 = (caract_face_2[2][7]+caract_face_1[2][7])/2.
1955     #rayon_2 = (caract_face_2[2][8]+caract_face_1[2][8])/2.
1956     caract_arete_face_1 = self._calcul_caract_aretes_face ( geompy, caract_face_1 )
1957     caract_arete_face_2 = self._calcul_caract_aretes_face ( geompy, caract_face_2 )
1958     rayon_1 = 0.
1959     rayon_2 = 0.
1960     for caract_aretes_face in [caract_arete_face_1,caract_arete_face_2]:
1961       prem = True
1962       for l_aux in caract_aretes_face:
1963         if ( l_aux[0] in ( geompy.kind.CIRCLE, geompy.kind.ARC_CIRCLE ) ):
1964           #print ("R =",l_aux[7])
1965           if prem:
1966             rayon_1 += l_aux[7]
1967             prem = False
1968           else:
1969             rayon_2 += l_aux[7]
1970     rayon_1 *= 0.5
1971     rayon_2 *= 0.5
1972 #   Hauteur
1973     hauteur = caract_face_1[2][9]
1974
1975     return coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur
1976
1977 #===========================  Fin de la méthode ==================================
1978
1979 #=========================== Début de la méthode =================================
1980
1981   def _cree_face_mediane_cone_1 ( self, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, rayon_1, rayon_2, hauteur ):
1982     """Crée la face médiane entre deux autres - cas des cones
1983
1984 Création des objets temporaires et de la face externe du cone support
1985
1986 Entrées :
1987   :coo_x, coo_y, coo_z: coordonnées du centre de la base
1988   :axe_x, axe_y, axe_z: coordonnées de l'axe
1989   :rayon_1, rayon_2: rayons moyens du côté de la base et à l'opposé
1990   :hauteur: hauteur du cone
1991
1992 Sorties :
1993   :face: la face externe du cone support
1994 """
1995     nom_fonction = __name__ + "/_cree_face_mediane_cone_1"
1996     blabla = "Dans {} :\n".format(nom_fonction)
1997
1998 #   Les deux faces
1999     if self._verbose_max:
2000       texte = blabla
2001       texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2002       texte += "Axe    : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2003       texte += "Rayons : {}, {}\n".format(rayon_1, rayon_2)
2004       texte += "Hauteur : {}".format(hauteur)
2005       print (texte)
2006
2007 #   Création du point central
2008     centre = model.addPoint(self.part_doc, coo_x, coo_y, coo_z)
2009     nom_centre = "{}_centre".format(self.nom_solide)
2010     centre.result().setName(nom_centre)
2011
2012 #   Création de l'axe
2013     axe = model.addAxis(self.part_doc, axe_x, axe_y, axe_z)
2014     nom_axe = "{}_axe".format(self.nom_solide)
2015     axe.result().setName(nom_axe)
2016
2017 #   Création d'un plan passant par ce centre et cet axe
2018     plan = model.addPlane(self.part_doc, model.selection("EDGE", nom_axe), model.selection("VERTEX", nom_centre), False)
2019     nom_plan = "{}_plan".format(self.nom_solide)
2020     plan.result().setName(nom_plan)
2021
2022 #   Création de l'esquisse
2023     nom_par_1 = "{}_R_1".format(self.nom_solide)
2024     model.addParameter(self.part_doc, "{}".format(nom_par_1), "{}".format(rayon_1))
2025     nom_par_2 = "{}_R_2".format(self.nom_solide)
2026     model.addParameter(self.part_doc, "{}".format(nom_par_2), "{}".format(rayon_2))
2027     nom_par_3 = "{}_H".format(self.nom_solide)
2028     model.addParameter(self.part_doc, "{}".format(nom_par_3), "{}".format(hauteur))
2029
2030     sketch = model.addSketch(self.part_doc, model.selection("FACE", nom_plan))
2031
2032     SketchProjection_1 = sketch.addProjection(model.selection("VERTEX", nom_centre), False)
2033     SketchPoint_1 = SketchProjection_1.createdFeature()
2034
2035     SketchProjection_2 = sketch.addProjection(model.selection("EDGE", nom_axe), False)
2036     SketchLine_1 = SketchProjection_2.createdFeature()
2037
2038     SketchLine_2 = sketch.addLine(coo_x, coo_y, coo_x+rayon_1, coo_y+hauteur)
2039     SketchLine_2.setAuxiliary(True)
2040     sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_2.startPoint())
2041     sketch.setParallel(SketchLine_1.result(), SketchLine_2.result())
2042     sketch.setLength(SketchLine_2.result(), nom_par_3)
2043
2044     SketchLine_3 = sketch.addLine(coo_x+rayon_1, coo_y, coo_x+rayon_1, coo_y+hauteur)
2045     sketch.setDistance(SketchLine_2.startPoint(), SketchLine_3.result(), nom_par_1, True)
2046     sketch.setDistance(SketchLine_2.endPoint(), SketchLine_3.result(), nom_par_2, True)
2047     sketch.setLength(SketchLine_3.result(), "2.5*{}".format(nom_par_3))
2048
2049     SketchPoint_2 = sketch.addPoint(coo_x, coo_y)
2050     sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_3.result())
2051     sketch.setMiddlePoint(SketchPoint_2.coordinates(), SketchLine_3.result())
2052
2053     SketchLine_4 = sketch.addLine(coo_x, coo_y, 1.2*coo_x, 1.2*coo_y)
2054     SketchLine_4.setAuxiliary(True)
2055     sketch.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.startPoint())
2056     sketch.setCoincident(SketchPoint_2.coordinates(), SketchLine_4.endPoint())
2057     sketch.setHorizontal(SketchLine_4.result())
2058
2059     model.do()
2060     nom_sketch = "{}_esquisse".format(self.nom_solide)
2061     sketch.setName(nom_sketch)
2062     sketch.result().setName(nom_sketch)
2063
2064 #   Création du cone complet
2065     nom_cone = "{}_cone".format(self.nom_solide)
2066     self._cree_revolution ( nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_cone )
2067
2068 #   Intersection de la face conique avec le solide initial
2069     face = self._creation_face_inter ( nom_cone )
2070
2071     return face
2072
2073 #===========================  Fin de la méthode ==================================
2074
2075 #=========================== Début de la méthode =================================
2076
2077   def _cree_centre_axe_plan ( self, coo_c, vnor, prefixe, n_recur ):
2078     """Crée un centre, un axe, un plan
2079
2080 Préparatifs
2081
2082 Entrées :
2083   :coo_c: coordonnées du centre de la base
2084   :vnor: coordonnées du vecteur normal
2085   :prefix: prefixe du nom des objets
2086   :n_recur: niveau de récursivité
2087
2088 Sorties :
2089   :centre: centre
2090   :normal: vecteur normal
2091   :plan: plan
2092 """
2093
2094     nom_fonction = __name__ + "/_cree_centre_axe_plan"
2095     blabla = "Dans {} :".format(nom_fonction)
2096     if self._verbose_max:
2097       print_tab (n_recur, blabla)
2098       print_tab (n_recur, "Centre   : ({}, {}, {})".format(coo_c[0], coo_c[1], coo_c[2]))
2099       print_tab (n_recur, "Normale  : ({}, {}, {})".format(vnor[0], vnor[1], vnor[2]))
2100
2101 #   Création du point central
2102     centre = model.addPoint(self.part_doc, coo_c[0], coo_c[1], coo_c[2])
2103     nom_centre = "{}_centre".format(prefixe)
2104     nommage (centre, nom_centre)
2105     model.do()
2106
2107 #   Création du vecteur normal
2108     v_norm = model.addAxis(self.part_doc, vnor[0], vnor[1], vnor[2])
2109     nom_vnorm = "{}_normale".format(prefixe)
2110     nommage (v_norm, nom_vnorm)
2111
2112 #   Création du plan perpendiculaire au vecteur normal
2113     plan = model.addPlane(self.part_doc, model.selection("EDGE", v_norm.name()), model.selection("VERTEX", centre.name()), True)
2114     nom_plan = "{}_plan".format(prefixe)
2115     nommage (plan, nom_plan)
2116
2117     print ("fin de {}".format(nom_fonction))
2118
2119     return centre, v_norm, plan
2120
2121 #===========================  Fin de la méthode ==================================
2122
2123 #=========================== Début de la méthode =================================
2124
2125   def _calcul_boite_englobante ( self, objet, n_recur ):
2126     """Crée la hauteur englobant à coup sûr l'objet
2127
2128 Entrées :
2129   :objet: l'objet à traiter
2130   :n_recur: niveau de récursivité
2131
2132 Sorties :
2133   :l_diag: longueur de la diagonale de la boîte englobante
2134 """
2135
2136     nom_fonction = __name__ + "/_calcul_boite_englobante"
2137     blabla = "Dans {} :".format(nom_fonction)
2138
2139     if self._verbose_max:
2140       print_tab (n_recur, blabla)
2141
2142 #   Hauteur : la diagonale de la boîte englobante permet d'être certain de tout prendre
2143     if self._verbose_max:
2144       print_tab (n_recur, "Création de la boite englobante pour l'objet ", objet.name())
2145       print_tab (n_recur, "de type ", objet.shapeType())
2146     #print ('bbox = model.getBoundingBox(self.part_doc, model.selection("{}", "{}"))'.format(objet.shapeType(),objet.name()))
2147     bbox = model.getBoundingBox(self.part_doc, model.selection("{}".format(objet.shapeType()), "{}".format(objet.name())))
2148     bbox.execute(True)
2149
2150     bbox_nom = bbox.name()
2151     if self._verbose_max:
2152       print_tab (n_recur, "Boîte englobante : '{}' '{}'".format(bbox.name(), bbox.result().name()))
2153
2154     if self._verbose_max:
2155       coo_min = model.getPointCoordinates(self.part_doc, \
2156       model.selection("VERTEX", "[{}_1/Back][{}_1/Left][{}_1/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)))
2157       coo_max = model.getPointCoordinates(self.part_doc, \
2158       model.selection("VERTEX", "[{}_1/Front][{}_1/Right][{}_1/Top]".format(bbox_nom,bbox_nom,bbox_nom)))
2159       texte = "Xmin = {}, Xmax = {}\n".format(coo_min[0],coo_max[0])
2160       texte += "\tYmin = {}, Ymax = {}\n".format(coo_min[1],coo_max[1])
2161       texte += "\tZmin = {}, Zmax = {}".format(coo_min[2],coo_max[2])
2162       print_tab (n_recur, texte)
2163
2164     l_diag = model.measureDistance(self.part_doc, \
2165       model.selection("VERTEX", "[{}_1/Back][{}_1/Left][{}_1/Bottom]".format(bbox_nom,bbox_nom,bbox_nom)), \
2166       model.selection("VERTEX", "[{}_1/Front][{}_1/Right][{}_1/Top]".format(bbox_nom,bbox_nom,bbox_nom)) )
2167     if self._verbose_max:
2168       print_tab (n_recur, "Longueur de la diagonale : ", l_diag)
2169
2170     return l_diag
2171
2172 #===========================  Fin de la méthode ==================================
2173
2174 #=========================== Début de la méthode =================================
2175
2176   def _cree_revolution ( self, nom_sketch, nom_centre, coo_x, coo_y, coo_z, axe_x, axe_y, axe_z, nom_objet ):
2177     """Crée un volume de révolution
2178
2179 Entrées :
2180   :nom_sketch: nom de l'esquisse à révolutionner
2181   :nom_centre: nom du point associé au centre du volume de révolution
2182   :coo_x, coo_y, coo_z: coordonnées du centre du tore
2183   :axe_x, axe_y, axe_z: coordonnées de l'axe
2184   :rayon_1 : rayon principal
2185   :rayon_2 : rayon secondaire
2186   :nom_objet: nom de l'objet 2D créé
2187 """
2188
2189     nom_fonction = __name__ + "/_cree_revolution"
2190     blabla = "Dans {} :\n".format(nom_fonction)
2191
2192     if self._verbose_max:
2193       texte = blabla
2194       texte += "Centre : ({}, {}, {})\n".format(coo_x, coo_y, coo_z)
2195       texte += "Axe    : ({}, {}, {})\n".format(axe_x, axe_y, axe_z)
2196       print (texte)
2197
2198 #   Création d'un point décalé par rapport au point central
2199     point = model.addPoint(self.part_doc, coo_x+axe_x, coo_y+axe_y, coo_z+axe_z)
2200     nom_point = "{}_point".format(self.nom_solide)
2201     point.result().setName(nom_point)
2202
2203 #   Création de l'axe de la rotation
2204     axe_r = model.addAxis(self.part_doc, model.selection("VERTEX", nom_centre), model.selection("VERTEX", nom_point))
2205     nom_axe_r = "{}_axe_r".format(self.nom_solide)
2206     axe_r.result().setName(nom_axe_r)
2207
2208 #   Création de l'objet complet
2209     objet = model.addRevolution(self.part_doc, [model.selection("COMPOUND", nom_sketch)], model.selection("EDGE", nom_axe_r), 360, 0, "Edges")
2210
2211     nommage (objet, nom_objet, (85, 0, 255))
2212
2213     return
2214
2215 #===========================  Fin de la méthode ==================================
2216
2217 #=========================== Début de la méthode =================================
2218
2219   def _creation_face_inter ( self, nom_objet ):
2220     """Crée la face par intersection entre l'objet initial et une face complète
2221
2222 . Repère la face principale de l'objet support
2223 . Réalise l'intersection avec le solide initial
2224
2225 Entrées :
2226   :nom_objet: nom de l'objet 2D créé
2227
2228 Sorties :
2229   :face: la face externe de l'objet support intersecté avec le solide initial
2230 """
2231
2232     nom_fonction = __name__ + "/_creation_face_inter"
2233     blabla = "Dans {} :\n".format(nom_fonction)
2234
2235     if self._verbose_max:
2236       print (blabla)
2237
2238     face = model.addCommon(self.part_doc, [model.selection("SOLID", self.nom_solide_aux), model.selection("FACE", nom_objet)], keepSubResults = True)
2239
2240     return face
2241
2242 #===========================  Fin de la méthode ==================================
2243
2244 #=========================== Début de la méthode =================================
2245
2246   def face_mediane_solide (self, solide, geompy, objet_geom, n_recur=0):
2247     """Calcul de la face médiane pour un solide
2248
2249 Entrées :
2250   :solide: solide SHAPER à traiter
2251   :geompy: environnement de GEOM
2252   :objet_geom: l'objet solide à traiter au format GEOM
2253   :n_recur: niveau de récursivité
2254
2255 Sorties :
2256   :erreur: code d'erreur
2257   :message: message d'erreur
2258 """
2259
2260     nom_fonction = __name__ + "/face_mediane_solide"
2261     blabla = "Dans {} :\n".format(nom_fonction)
2262
2263     if self._verbose_max:
2264       print_tab (n_recur, blabla, saut_av=True)
2265     if self._verbose:
2266       print_tab (n_recur, "Traitement du solide ", solide.name())
2267
2268 # 1. Préalables
2269
2270     erreur = 0
2271     message = ""
2272
2273     while not erreur :
2274
2275 # 2. Explosion du solide en faces
2276
2277       erreur, message, l_faces_geom, l_faces = self._faces_du_solide ( geompy, objet_geom, solide, n_recur )
2278       if erreur:
2279         break
2280
2281 # 3. Calcul des caractéristiques géométriques des faces
2282
2283       tb_caract = self._calcul_caract_faces ( geompy, l_faces_geom, n_recur )
2284
2285 # 4. Tri des faces en fonction de leurs caractéristiques géométriques
2286
2287       erreur, message, caract_face_1, caract_face_2 = self._tri_faces ( tb_caract, n_recur )
2288       if erreur:
2289         break
2290
2291 # 5. Création de la face médiane
2292
2293       erreur, face = self._cree_face_mediane ( solide, geompy, caract_face_1, caract_face_2, n_recur )
2294       if erreur:
2295         break
2296
2297 # 6. Exportation step
2298
2299       if self._export_step:
2300         fichier = os.path.join(self.rep_step, "{}.stp".format(face.result().name()))
2301         export = model.exportToFile(self.part_doc, fichier, [model.selection(face.result().shapeType(), face.result().name())])
2302         export.execute(True)
2303         model.do()
2304
2305 # 7. La fin
2306
2307       break
2308
2309     if ( erreur and self._verbose_max ):
2310       print (blabla, message)
2311
2312     return erreur, message
2313
2314 #===========================  Fin de la méthode ==================================
2315
2316 #=========================== Début de la méthode =================================
2317
2318   def _traitement_objet (self, solide=None, objet_geom=None, n_recur=0):
2319     """Traitement d'un objet
2320
2321 Entrées :
2322   :solide: solide SHAPER à traiter
2323   :objet_geom: l'objet GEOM équivalent
2324   :n_recur: niveau de récursivité
2325
2326 Sorties :
2327   :erreur: code d'erreur
2328   :message: message d'erreur
2329 """
2330
2331     nom_fonction = __name__ + "/_traitement_objet"
2332     blabla = "Dans {} :".format(nom_fonction)
2333
2334     if self._verbose_max:
2335       print_tab (n_recur, blabla, saut_av=True)
2336       print_tab (n_recur, "solide = " , solide)
2337       print_tab (n_recur, "objet_geom = ", objet_geom)
2338
2339 # 1. Préalables
2340
2341     erreur = 0
2342     message = ""
2343
2344     while not erreur :
2345
2346 # 2. L'aide
2347
2348       if self.affiche_aide_globale :
2349         break
2350
2351 # 3. Les imports pour salomé
2352       geompy = geomBuilder.New()
2353
2354 # 4. En cas d'exportation step, répertoire de travail associé à l'éventuel fichier de départ
2355 #    Attention à ne pas recréer le répertoire à chaque fois
2356       if self._export_step:
2357
2358         if self._verbose_max:
2359           print_tab (n_recur, "Préparation de l'export STEP")
2360
2361         if self.rep_step is None:
2362           if self.ficcao is None:
2363             self.rep_step = tempfile.mkdtemp(prefix="{}_".format(self.objet_principal.name()))
2364           else:
2365             self.rep_step = os.path.join(os.path.dirname(self.ficcao),"{}_M".format(self.objet_principal.name()))
2366             if os.path.isdir(self.rep_step):
2367               l_aux = os.listdir(self.rep_step)
2368               for nomfic in l_aux:
2369                 os.remove(os.path.join(self.rep_step,nomfic))
2370             else:
2371               os.mkdir(self.rep_step)
2372         if self._verbose_max:
2373           print_tab (n_recur, "Les fichiers CAO des surfaces seront dans le répertoire {}".format(self.rep_step))
2374
2375 # 5. Calcul réel de la face médiane
2376
2377       if solide is None:
2378         self.nom_solide = objet_geom.GetName()
2379
2380       erreur, message = self.face_mediane_solide (solide, geompy, objet_geom, n_recur)
2381       if erreur:
2382         break
2383
2384       break
2385
2386     return erreur, message
2387
2388 #===========================  Fin de la méthode ==================================
2389
2390 #=========================== Début de la méthode =================================
2391
2392   def surf_fic_cao (self, ficcao, nom_objet=None):
2393     """Calcule la surface médiane pour un objet dans un fichier passé en argument
2394
2395 Entrées :
2396   :ficcao: fichier de l'objet à traiter
2397   :nom_objet: un nom à donner à l'objet à traiter
2398
2399 Sorties :
2400   :erreur: code d'erreur
2401   :message: message d'erreur
2402 """
2403
2404     nom_fonction = __name__ + "/surf_fic_cao"
2405     blabla = "Dans {} :\n".format(nom_fonction)
2406
2407     if self._verbose_max:
2408       print (blabla)
2409
2410     erreur = 0
2411     message = ""
2412
2413     model.begin()
2414
2415     while not erreur :
2416
2417 # 1. Définition de la pièce
2418
2419       self.part_doc = model.activeDocument()
2420       if ( self.part_doc.kind() == "PartSet" ):
2421         part = model.addPart(self.part_doc)
2422         self.part_doc = part.document()
2423
2424 # 2. Import de la CAO
2425
2426       self.ficcao = ficcao
2427       print ("Traitement du fichier {}".format(ficcao))
2428
2429       erreur, message, objet = import_cao (self.part_doc, ficcao, nom_objet, self._verbose_max)
2430       if erreur:
2431         break
2432
2433 # 3. Calcul des surfaces
2434
2435       erreur, message = self.surf_objet_shaper ( objet )
2436       if erreur:
2437         break
2438       #print (message)
2439
2440       break
2441
2442     model.end()
2443
2444     if ( erreur and self._verbose_max ):
2445       print (blabla, message)
2446
2447     return erreur, message
2448
2449 #===========================  Fin de la méthode ==================================
2450
2451 #=========================== Début de la méthode =================================
2452
2453   def surf_objet_shaper (self, objet):
2454     """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2455
2456 Entrées :
2457   :objet: objet à traiter
2458
2459 Sorties :
2460   :erreur: code d'erreur
2461   :message: message d'erreur
2462 """
2463
2464     nom_fonction = __name__ + "/surf_objet_shaper"
2465     blabla = "Dans {} :".format(nom_fonction)
2466
2467     if self._verbose_max:
2468       print (blabla)
2469
2470 # 1. Acquisition de la liste des noms des sous-objets solides
2471
2472     self.d_statut_so = dict()
2473     self.l_noms_so = list()
2474     self.l_faces_m = list()
2475
2476     _ = self._nom_sous_objets (objet, True)
2477     if self._verbose_max:
2478       print ("Noms des sous-objets : {}".format(self.l_noms_so))
2479
2480 # 2. Les faces médianes
2481
2482     erreur, message = self._surf_objet_shaper_0 ( objet )
2483
2484 # 3. Gestion des faces créées
2485
2486     self._surf_objet_shaper_1 ( )
2487
2488 # 4. Futur message pour le résultat
2489
2490     if ( self._export_step and not erreur ):
2491       message = "Les fichiers des CAO des surfaces sont dans le répertoire {}".format(self.rep_step)
2492
2493     return erreur, message
2494
2495 #===========================  Fin de la méthode ==================================
2496
2497 #=========================== Début de la méthode =================================
2498
2499   def _surf_objet_shaper_0 (self, objet, n_recur=0):
2500     """Calcule les surfaces médianes pour un objet SHAPER passé en argument
2501
2502 Entrées :
2503   :objet: objet à traiter
2504   :n_recur: niveau de récursivité
2505
2506 Sorties :
2507   :erreur: code d'erreur
2508   :message: message d'erreur
2509 """
2510
2511     nom_fonction = __name__ + "/_surf_objet_shaper_0"
2512     blabla = "Dans {} :\n".format(nom_fonction)
2513
2514     if self._verbose_max:
2515       print_tab (n_recur, blabla)
2516       print_tab (n_recur, "n_recur = ", n_recur)
2517
2518     erreur = 0
2519     message = ""
2520
2521     while not erreur :
2522
2523 # 1. Au premier passage, il faut récupérer la pièce et garder la référence au résultat principal
2524
2525       if ( n_recur == 0 ):
2526         self.part_doc = model.activeDocument()
2527         objet_0, l_faces = self._surf_objet_shaper_00 (objet)
2528       else:
2529         objet_0 = objet
2530         print_tab (n_recur, "Examen de l'objet ", objet.name(), saut_av=True)
2531         print_tab (n_recur, "Type python : ", type(objet))
2532         print_tab (n_recur, "Type ", objet.shapeType())
2533
2534 # 2. On descend dans l'arborescence des sous-objets jusqu'à en trouver un qui n'en n'a pas
2535
2536       nb_sub_results = objet_0.numberOfSubs()
2537
2538       if self._verbose_max:
2539         print_tab (n_recur, "Examen de l'objet '{}' de type ".format(objet_0.name()), objet_0.shapeType(), saut_av=True)
2540         print_tab (n_recur, "objet.result().numberOfSubs() : ", nb_sub_results)
2541
2542       for n_sobj in range(nb_sub_results):
2543
2544 # 2.1. Exploration récursive de l'arborescence
2545
2546         erreur, message = self._surf_objet_shaper_0 ( objet_0.subResult(n_sobj), n_recur+1 )
2547         if erreur:
2548           break
2549
2550       if erreur:
2551         break
2552
2553 # 2.2. Cet objet n'a pas de sous-objets. Si c'est un solide, on le traite
2554
2555       if ( objet_0.shapeType() == "SOLID" ):
2556         erreur, message = self.surf_solide_shaper ( objet_0, n_recur )
2557         if erreur:
2558           break
2559
2560 # 3. Futur message pour le résultat
2561
2562       if self._export_step:
2563         message = "Les fichiers STEP des surfaces sont dans le répertoire {}".format(self.rep_step)
2564
2565       break
2566
2567     return erreur, message
2568
2569 #===========================  Fin de la méthode ==================================
2570
2571 #=========================== Début de la méthode =================================
2572
2573   def _surf_objet_shaper_00 (self, objet):
2574     """Liste les faces d'un objet SHAPER passé en argument
2575
2576 Entrées :
2577   :objet: objet à traiter
2578
2579 Sorties :
2580   :objet_0: le résultat associé à l'objet
2581   :l_faces: liste des faces
2582 """
2583
2584     nom_fonction = __name__ + "/_surf_objet_shaper_00"
2585     blabla = "Dans {} :\n".format(nom_fonction)
2586
2587     if self._verbose_max:
2588       print (blabla)
2589
2590 # 1. Objet principal
2591     objet_0 = objet.result()
2592     self.objet_principal = objet_0
2593     objet_bis = objet.defaultResult().shape()
2594     if self._verbose_max:
2595       print_tab (0, "Examen de l'objet initial ", objet.result().name(), saut_av=True)
2596       print_tab (0, "Type python : ", type(objet))
2597       print_tab (0, "Type {} / {} ; volume = ".format(objet_bis.shapeType(),objet_bis.shapeTypeStr()), GeomAlgoAPI_ShapeTools.volume(objet_bis))
2598
2599 # 2. Décomposition
2600 # 2.1. En volumes
2601     l_volumes = list()
2602     exp = GeomAPI_ShapeExplorer(objet_bis, GeomAPI_Shape.SOLID)
2603     while exp.more():
2604       l_volumes.append(exp.current().solid())
2605       exp.next()
2606
2607 # 2.2. Chaque volume en faces
2608     for ivolume, volume in enumerate(l_volumes):
2609
2610       if self._verbose_max:
2611         print_tab (1, "Volume n°{} ; volume = ".format(ivolume), GeomAlgoAPI_ShapeTools.volume(volume))
2612         print_tab (1, "Type python : ", type(volume))
2613         print_tab (1, "Type {} / ".format(volume.shapeType()), volume.shapeTypeStr())
2614         #print ("\tInformations : {}".format(volume.shapeInfo()))
2615
2616       l_faces = list()
2617       exp = GeomAPI_ShapeExplorer(volume, GeomAPI_Shape.FACE)
2618       while exp.more():
2619         l_faces.append(exp.current().face())
2620         exp.next()
2621
2622       if self._verbose_max:
2623         for iface, face in enumerate(l_faces):
2624           print_tab (2, "Face n°{} ; surface = ".format(iface), GeomAlgoAPI_ShapeTools.area(face))
2625
2626     return objet_0, l_faces
2627
2628 #===========================  Fin de la méthode ==================================
2629
2630 #=========================== Début de la méthode =================================
2631
2632   def _surf_objet_shaper_1 (self, n_recur=0):
2633     """Gestion des surfaces médianes créées
2634
2635 Entrées :
2636   :n_recur: niveau de récursivité
2637
2638 Sorties :
2639   :erreur: code d'erreur
2640   :message: message d'erreur
2641 """
2642
2643     nom_fonction = __name__ + "/_surf_objet_shaper_1"
2644     blabla = "Dans {} :\n".format(nom_fonction)
2645
2646     if self._verbose_max:
2647       print_tab (n_recur, blabla)
2648
2649 # 1. Informations sur les faces à problème
2650
2651     if self.faces_pb_nb:
2652       if ( self.faces_pb_nb == 1 ):
2653         texte = "1 face pose"
2654       else:
2655         texte = "{} faces posent".format(self.faces_pb_nb)
2656       print_tab (n_recur, "{} problème.".format(texte), self.faces_pb_msg, saut_av=True)
2657
2658 # 2. Si plus d'une face a été créée
2659     if ( len(self.l_faces_m) > 1 ):
2660
2661 # 2.1. Partition du paquet de faces
2662
2663       if self._verbose_max:
2664         print_tab (n_recur, "Partitionnnement des faces créées.")
2665
2666       l_objets = list()
2667       for (face,_) in self.l_faces_m:
2668         l_objets.append(model.selection("COMPOUND", "all-in-{}".format(face.name())))
2669
2670       Partition_1 = model.addPartition(self.part_doc, l_objets, keepSubResults = True)
2671
2672       Partition_1.result().setName("{}_M".format(self.objet_principal.name()))
2673       for iaux, (face,_) in enumerate(self.l_faces_m):
2674         Partition_1.result().subResult(iaux).setName("{}".format(face.name()))
2675       self._couleur_objet (Partition_1, n_recur, coul_r=0, coul_g=170, coul_b=0)
2676
2677 # 2.2. Récupération des faces individuelles
2678
2679       if self._verbose_max:
2680         print_tab (n_recur, "Récupération des faces individuelles.")
2681
2682       l_objets = list()
2683       for iaux, (face,_) in enumerate(self.l_faces_m):
2684         l_objets.append(face.result())
2685
2686       Recover_1 = model.addRecover(self.part_doc, Partition_1, l_objets)
2687       for iaux, (face,_) in enumerate(self.l_faces_m):
2688         Recover_1.results()[iaux].setName("{}".format(face.name()))
2689         Recover_1.results()[iaux].setColor(0, 170, 0)
2690
2691 # 2.3. Mise en dossier
2692
2693       if self._verbose_max:
2694         print_tab (n_recur, "Mise en dossier.")
2695
2696       for (face,fonction_0) in self.l_faces_m:
2697         dossier = model.addFolder(self.part_doc, fonction_0, face)
2698         dossier.setName(face.name()[:-2])
2699
2700     return
2701
2702 #===========================  Fin de la méthode ==================================
2703
2704 #=========================== Début de la méthode =================================
2705
2706   def surf_solide_shaper (self, solide, n_recur):
2707     """Calcule les surfaces médianes pour un solide SHAPER solide passé en argument
2708
2709 Entrées :
2710   :solide: solide SHAPER à traiter
2711   :n_recur: numéro de la récurrence
2712
2713 Sorties :
2714   :erreur: code d'erreur
2715   :message: message d'erreur
2716 """
2717
2718     nom_fonction = __name__ + "/surf_solide_shaper"
2719     blabla = "Dans {} :".format(nom_fonction)
2720
2721     if self._verbose_max:
2722       print_tab (n_recur, blabla, saut_av=True)
2723
2724     erreur = 0
2725     message = ""
2726
2727     while not erreur :
2728
2729       self.nom_solide = solide.name()
2730       if self._verbose_max:
2731         print_tab (n_recur, "solide : ", self.nom_solide)
2732
2733 # 1. Isolement du solide
2734       solide_aux, recover = self._isole_solide ( solide, n_recur )
2735
2736 # 2. Exportation dans un fichier step pour traitement dans GEOM
2737
2738       fichier = tempfile.mkstemp(suffix=".stp")[1]
2739       if self._verbose_max:
2740         print_tab (n_recur, "fichier = ", fichier)
2741         print_tab (n_recur, "solide  = ", solide_aux.name())
2742         print_tab (n_recur, "de type = ", solide_aux.shapeType())
2743       export = model.exportToFile(self.part_doc, fichier, [model.selection(solide_aux.shapeType(), solide_aux.name())])
2744       export.execute(True)
2745       model.do()
2746
2747       taille = os.path.getsize(fichier)
2748       if ( taille <= 0 ):
2749         message = "Export de SHAPER vers GEOM impossible pour le solide '{}' de type '{}'\n".format(solide_aux.name(), solide_aux.shapeType())
2750         message += "Le fichier {} est de taille {}".format(fichier,taille)
2751         erreur = 2
2752         break
2753
2754 # 3. Importation dans GEOM
2755       geompy = geomBuilder.New()
2756       objet_geom = geompy.ImportSTEP(fichier, False, True)
2757       os.remove(fichier)
2758
2759 # 4. Traitement de l'objet correspondant
2760       erreur, message = self._traitement_objet ( solide=solide_aux, objet_geom=objet_geom, n_recur=n_recur )
2761
2762       if ( erreur and self._verbose_max ):
2763         print (blabla, message)
2764
2765 # 5. Mise en forme de l'objet principal récupéré
2766       if ( recover is not None ):
2767         _ = self._nom_sous_objets (recover, False)
2768
2769 # 6. Neutralisation des erreurs dues à l'épaisseur
2770       if ( erreur in (-2,-1,2) ):
2771         erreur = 0
2772         message = ""
2773
2774       break
2775
2776     return erreur, message
2777
2778 #===========================  Fin de la méthode ==================================
2779
2780 #=========================== Début de la méthode =================================
2781
2782   def surf_objet_geom (self, objet_geom):
2783     """Calcule la surface médiane pour un objet GEOM passé en argument
2784
2785 Entrées :
2786   :objet_geom: l'objet GEOM à traiter
2787
2788 Sorties :
2789   :erreur: code d'erreur
2790   :message: message d'erreur
2791 """
2792
2793     nom_fonction = __name__ + "/surf_objet_geom"
2794     blabla = "Dans {} :\n".format(nom_fonction)
2795
2796     if self._verbose_max:
2797       print (blabla)
2798
2799     erreur, message = self._traitement_objet ( objet_geom=objet_geom )
2800
2801     if ( erreur and self._verbose_max ):
2802       print (blabla, message)
2803
2804     return erreur, message
2805
2806 #===========================  Fin de la méthode ==================================
2807
2808 #=========================== Début de la méthode =================================
2809
2810   def lancement (self):
2811
2812     """Lancement
2813
2814 Sorties :
2815   :erreur: code d'erreur
2816   :message: message d'erreur
2817 """
2818
2819     nom_fonction = __name__ + "/lancement"
2820     blabla = "Dans {} :\n".format(nom_fonction)
2821
2822     if self._verbose_max:
2823       print (blabla)
2824
2825     erreur, message = self._traitement_objet ( )
2826
2827     if ( erreur and self._verbose_max ):
2828       print (blabla, message)
2829
2830     return erreur, message
2831
2832 #===========================  Fin de la méthode ==================================
2833
2834 #==========================  Fin de la classe ====================================
2835
2836 #==================================================================================
2837 # Lancement
2838 #==================================================================================
2839
2840 if __name__ == "__main__" :
2841
2842   HOME_SH_SM_EXCHANGE = os.environ["HOME_SH_SM_EXCHANGE"]
2843   L_FIC_CAO = list()
2844   #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "Solid_7.step"))
2845   #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Objet_1.stp"))
2846   #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval_007.stp"))
2847   ##L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Naval.stp"))
2848   #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2.step"))
2849   #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_22.step"))
2850   #L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Partition_2_1_5.step"))
2851   L_FIC_CAO.append(os.path.join(HOME_SH_SM_EXCHANGE, "SHAPER", "SurfaceMediane", "CAO_STEP", "Observatoire.stp"))
2852
2853   for FIC_CAO in L_FIC_CAO:
2854
2855 # 1. Options
2856
2857     L_OPTIONS = list()
2858     #L_OPTIONS.append("-h")
2859     #L_OPTIONS.append("-v")
2860     L_OPTIONS.append("-vmax")
2861     L_OPTIONS.append("-export_step")
2862
2863 # 2. Lancement de la classe
2864
2865     #print ("L_OPTIONS :", L_OPTIONS)
2866
2867     SURFACE_MEDIANE = SurfaceMediane(L_OPTIONS)
2868     if SURFACE_MEDIANE.affiche_aide_globale:
2869       sys.stdout.write(SURFACE_MEDIANE.__doc__+"\n")
2870     else:
2871       model.begin()
2872       PARTSET = model.moduleDocument()
2873       _ = model.addPart(PARTSET)
2874       ERREUR, MESSAGE_ERREUR = SURFACE_MEDIANE.surf_fic_cao(FIC_CAO)
2875       if ERREUR:
2876         MESSAGE_ERREUR += "\n Code d'erreur : %d\n" % ERREUR
2877         sys.stderr.write(MESSAGE_ERREUR)
2878         break
2879
2880     del SURFACE_MEDIANE
2881
2882   #sys.exit(0)