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