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