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