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