Salome HOME
PR: add blocFissure plugin
[modules/smesh.git] / src / Tools / blocFissure / gmu / insereFissureGenerale.py
diff --git a/src/Tools/blocFissure/gmu/insereFissureGenerale.py b/src/Tools/blocFissure/gmu/insereFissureGenerale.py
new file mode 100644 (file)
index 0000000..3204084
--- /dev/null
@@ -0,0 +1,1371 @@
+# -*- coding: utf-8 -*-
+
+import logging
+import salome
+from geomsmesh import geompy
+import GEOM
+from geomsmesh import smesh
+from salome.smesh import smeshBuilder
+import SMESH
+import math
+import bisect
+
+from extractionOrientee import extractionOrientee
+from extractionOrienteeMulti import extractionOrienteeMulti
+from sortFaces import sortFaces
+from sortEdges import sortEdges
+from eliminateDoubles import eliminateDoubles
+from substractSubShapes import substractSubShapes
+from produitMixte import produitMixte
+from findWireEndVertices import findWireEndVertices
+from findWireIntermediateVertices import findWireIntermediateVertices
+from orderEdgesFromWire import orderEdgesFromWire
+from getSubshapeIds import getSubshapeIds
+from putName import putName
+from distance2 import distance2
+from enleveDefaut import enleveDefaut
+from shapeSurFissure import shapeSurFissure
+from regroupeSainEtDefaut import RegroupeSainEtDefaut
+from triedreBase import triedreBase
+from checkDecoupePartition import checkDecoupePartition
+from whichSide import whichSide
+from whichSideMulti import whichSideMulti
+from whichSideVertex import whichSideVertex
+from projettePointSurCourbe import projettePointSurCourbe
+from prolongeWire import prolongeWire
+#from getCentreFondFiss import getCentreFondFiss
+
+# -----------------------------------------------------------------------------
+# --- procédure complète fissure générale
+
+def insereFissureGenerale(maillagesSains,
+                          shapesFissure, shapeFissureParams,
+                          maillageFissureParams, elementsDefaut, step=-1):
+  """
+  TODO: a completer
+  """
+  logging.info('start')
+  
+  shapeDefaut       = shapesFissure[0] # faces de fissure, débordant
+  fondFiss          = shapesFissure[4] # groupe d'edges de fond de fissure
+
+  rayonPipe = shapeFissureParams['rayonPipe']
+  if shapeFissureParams.has_key('lenSegPipe'):
+    lenSegPipe = shapeFissureParams['lenSegPipe']
+  else:
+    lenSegPipe = rayonPipe
+
+  nomRep            = maillageFissureParams['nomRep']
+  nomFicSain        = maillageFissureParams['nomFicSain']
+  nomFicFissure     = maillageFissureParams['nomFicFissure']
+
+  nbsegRad          = maillageFissureParams['nbsegRad']      # nombre de couches selon un rayon du pipe
+  nbsegCercle       = maillageFissureParams['nbsegCercle']   # nombre de secteur dans un cercle du pipe
+  areteFaceFissure  = maillageFissureParams['areteFaceFissure']
+
+  pointIn_x = 0.0
+  pointIn_y = 0.0
+  pointIn_z = 0.0
+  isPointInterne = False
+  if shapeFissureParams.has_key('pointIn_x'):
+    pointIn_x = shapeFissureParams['pointIn_x']
+    isPointInterne = True
+  if shapeFissureParams.has_key('pointIn_y'):
+    pointIn_y = shapeFissureParams['pointIn_y']
+    isPointInterne = True
+  if shapeFissureParams.has_key('pointIn_z'):
+    pointIn_z = shapeFissureParams['pointIn_z']
+    isPointInterne = True
+  if isPointInterne:
+    pointInterne = geompy.MakeVertex(pointIn_x, pointIn_y, pointIn_z)
+
+  #fichierMaillageSain = nomRep + '/' + nomFicSain + '.med'
+  fichierMaillageFissure = nomRep + '/' + nomFicFissure + '.med'
+
+  facesDefaut              = elementsDefaut[0] # fillings des faces en peau 
+  #centresDefaut            = elementsDefaut[1]
+  #normalsDefaut            = elementsDefaut[2]
+  #extrusionsDefaut         = elementsDefaut[3]
+  dmoyen                   = elementsDefaut[4]
+  bordsPartages            = elementsDefaut[5]
+  fillconts                = elementsDefaut[6]
+  idFilToCont              = elementsDefaut[7]
+  maillageSain             = elementsDefaut[8]
+  internalBoundary         = elementsDefaut[9]
+  zoneDefaut               = elementsDefaut[10]
+  zoneDefaut_skin          = elementsDefaut[11]
+  zoneDefaut_internalFaces = elementsDefaut[12]
+  zoneDefaut_internalEdges = elementsDefaut[13]
+  edgeFondExt              = elementsDefaut[14]
+  centreFondFiss           = elementsDefaut[15]
+  tgtCentre                = elementsDefaut[16]
+
+  # --- restriction de la face de fissure au domaine solide :
+  #     partition face fissure étendue par fillings, on garde la plus grande face
+
+  partShapeDefaut = geompy.MakePartition([shapeDefaut], facesDefaut, [], [], geompy.ShapeType["FACE"], 0, [], 0)
+  geompy.addToStudy(partShapeDefaut, 'partShapeDefaut')
+  facesPartShapeDefaut = geompy.ExtractShapes(partShapeDefaut, geompy.ShapeType["FACE"], False)
+  if isPointInterne:
+    distfaces = [(geompy.MinDistance(face,pointInterne), i, face) for i, face in enumerate(facesPartShapeDefaut)]
+    distfaces.sort()
+    logging.debug("selection de la face la plus proche du point interne, distance=%s",distfaces[0][0])
+    facesPortFissure = distfaces[0][2]
+  else:
+    facesPartShapeDefautSorted, minSurf, maxSurf = sortFaces(facesPartShapeDefaut) # la face de fissure dans le volume doit être la plus grande
+    logging.debug("surfaces faces fissure étendue, min %s, max %s", minSurf, maxSurf)
+    facesPortFissure = facesPartShapeDefautSorted[-1]
+  
+  geompy.addToStudy(facesPortFissure, "facesPortFissure")
+
+  O, OX, OY, OZ = triedreBase()
+  
+  # -----------------------------------------------------------------------------
+  # --- pipe de fond de fissure, prolongé, partition face fissure par pipe
+  #     identification des edges communes pipe et face fissure
+  
+  if geompy.NumberOfFaces(shapeDefaut) == 1:
+    plan = geompy.MakePlane(centreFondFiss, tgtCentre, 10000)
+    shapeDefaut = geompy.MakePartition([shapeDefaut], [plan], [], [], geompy.ShapeType["FACE"], 0, [], 0)
+    fondFissCoupe = geompy.GetInPlaceByHistory(shapeDefaut, fondFiss)
+    geompy.addToStudy(shapeDefaut, 'shapeDefaut_coupe')
+    geompy.addToStudyInFather(shapeDefaut, fondFissCoupe, 'fondFiss_coupe')
+  
+  extrem, norms = findWireEndVertices(fondFiss, True)
+  logging.debug("extrem: %s, norm: %s",extrem, norms)
+  cercle = geompy.MakeCircle(extrem[0], norms[0], rayonPipe)
+  cercle = geompy.MakeRotation(cercle, norms[0], math.pi/3.0 ) # éviter d'avoir l'arête de couture du pipe presque confondue avec la face fissure
+  geompy.addToStudy(cercle, 'cercle')
+  fondFissProlonge = prolongeWire(fondFiss, extrem, norms, 2*rayonPipe)
+  pipeFiss = geompy.MakePipe(cercle, fondFissProlonge)
+  geompy.addToStudy(pipeFiss, 'pipeFiss')
+  partFissPipe = geompy.MakePartition([shapeDefaut, pipeFiss], [], [], [], geompy.ShapeType["FACE"], 0, [], 1)
+  geompy.addToStudy(partFissPipe, 'partFissPipe')
+  fissPipe = geompy.GetInPlaceByHistory(partFissPipe, shapeDefaut)
+  geompy.addToStudy(fissPipe, 'fissPipe')
+  partPipe = geompy.GetInPlaceByHistory(partFissPipe, pipeFiss)
+  geompy.addToStudy(partPipe, 'partPipe')
+  
+  edgesPipeFiss = geompy.GetSharedShapesMulti([fissPipe, partPipe], geompy.ShapeType["EDGE"])
+  for i, edge in enumerate(edgesPipeFiss):
+    name = "edgePipe%d"%i
+    geompy.addToStudyInFather(fissPipe, edge, name)
+  try:
+    wirePipeFiss = geompy.MakeWire(edgesPipeFiss)
+  except:
+    wirePipeFiss = geompy.MakeCompound(edgesPipeFiss)
+    logging.debug("wirePipeFiss construit sous forme de compound")
+  geompy.addToStudy(wirePipeFiss, "wirePipeFiss")
+  
+  wireFondFiss = geompy.GetInPlace(partFissPipe,fondFiss)
+  edgesFondFiss = geompy.GetSharedShapesMulti([fissPipe, wireFondFiss], geompy.ShapeType["EDGE"])
+  for i, edge in enumerate(edgesFondFiss):
+    name = "edgeFondFiss%d"%i
+    geompy.addToStudyInFather(fissPipe, edge, name)
+  wireFondFiss = geompy.MakeWire(edgesFondFiss)
+  geompy.addToStudy(wireFondFiss,"wireFondFiss")  
+
+  # -----------------------------------------------------------------------------
+  # --- peau et face de fissure
+  #
+  # --- partition peau défaut - face de fissure prolongée - wire de fond de fissure prolongée
+  #     il peut y avoir plusieurs faces externes, dont certaines sont découpées par la fissure
+  #     liste de faces externes : facesDefaut
+  #     liste de partitions face externe - fissure : partitionPeauFissFond (None quand pas d'intersection)
+  
+  partitionsPeauFissFond = []
+  ipart = 0
+  for filling in facesDefaut: 
+    part = geompy.MakePartition([fissPipe, filling], [], [], [], geompy.ShapeType["FACE"], 0, [], 0)
+    isPart = checkDecoupePartition([fissPipe, filling], part)
+    if isPart: # on recrée la partition avec toutes les faces filling en outil pour avoir une face de fissure correcte
+      otherFD = [fd for fd in facesDefaut if fd != filling]
+      if len(otherFD) > 0:
+        fissPipePart = geompy.MakePartition([fissPipe], otherFD, [], [], geompy.ShapeType["FACE"], 0, [], 0)
+      else:
+        fissPipePart = fissPipe
+      part = geompy.MakePartition([fissPipePart, filling], [], [], [], geompy.ShapeType["FACE"], 0, [], 0)
+      partitionsPeauFissFond.append(part)
+      geompy.addToStudy( part, 'partitionPeauFissFond%d'%ipart )
+    else:
+      partitionsPeauFissFond.append(None)
+    ipart = ipart +1
+  
+  # --- arêtes vives détectées (dans quadranglesToShape)
+   
+  aretesVives = []
+  aretesVivesCoupees = []
+  ia = 0
+  for a in bordsPartages:
+    if a[0] is not None:
+      aretesVives.append(a[0])
+      name = "areteVive%d"%ia
+      geompy.addToStudy(a[0], name)
+      ia += 1
+  aretesVivesC = None
+  if len(aretesVives) > 0:
+    aretesVivesC =geompy.MakeCompound(aretesVives)
+    
+  # -------------------------------------------------------
+  # --- inventaire des faces de peau coupées par la fissure
+  #     pour chaque face de peau : 0, 1 ou 2 faces débouchante du fond de fissure
+  #                                0, 1 ou plus edges de la face de fissure externe au pipe
+  
+  nbFacesFilling = len(partitionsPeauFissFond)
+  ptEdgeFond = [ []  for i in range(nbFacesFilling)] # pour chaque face [points edge fond de fissure aux débouchés du pipe]
+  fsPipePeau = [ []  for i in range(nbFacesFilling)] # pour chaque face [faces du pipe débouchantes]
+  edRadFPiPo = [ []  for i in range(nbFacesFilling)] # pour chaque face [edge radiale des faces du pipe débouchantes ]
+  fsFissuExt = [ []  for i in range(nbFacesFilling)] # pour chaque face [faces de fissure externes au pipe]
+  edFisExtPe = [ []  for i in range(nbFacesFilling)] # pour chaque face [edge en peau des faces de fissure externes (pas subshape facePeau)]
+  edFisExtPi = [ []  for i in range(nbFacesFilling)] # pour chaque face [edge commun au pipe des faces de fissure externes]
+  facesPeaux = [None for i in range(nbFacesFilling)] # pour chaque face : la face de peau finale a mailler (percée des faces débouchantes)
+  edCircPeau = [ []  for i in range(nbFacesFilling)] # pour chaque face de peau : [subshape edge circulaire aux débouchés du pipe]
+  ptCircPeau = [ []  for i in range(nbFacesFilling)] # pour chaque face de peau : [subshape point sur edge circulaire aux débouchés du pipe]
+  gpedgeBord = [None for i in range(nbFacesFilling)] # pour chaque face de peau : groupe subshape des edges aux bords liés à la partie saine
+  gpedgeVifs = [None for i in range(nbFacesFilling)] # pour chaque face de peau : groupes subshape des edges aux arêtes vives entre fillings
+  edFissPeau = [ []  for i in range(nbFacesFilling)] # pour chaque face de peau : [subshape edge en peau des faces de fissure externes]
+  ptFisExtPi = [ []  for i in range(nbFacesFilling)] # pour chaque face de peau : [point commun edFissPeau edCircPeau]
+  
+  for ifil, partitionPeauFissFond in enumerate(partitionsPeauFissFond):
+    fillingFaceExterne = facesDefaut[ifil]
+    fillingSansDecoupe = fillconts[idFilToCont[ifil]]
+    if partitionPeauFissFond is not None:
+      logging.debug("traitement partitionPeauFissFond %s", ifil)
+      # -----------------------------------------------------------------------
+      # --- identification edges fond de fissure, edges pipe sur la face de fissure,
+      #     edges prolongées
+      
+      edgesPipeC = geompy.GetInPlace(partitionPeauFissFond, geompy.MakeCompound(edgesPipeFiss))
+      geompy.addToStudyInFather(partitionPeauFissFond, edgesPipeC, "edgesPipeFiss")
+      edgesFondC = geompy.GetInPlace(partitionPeauFissFond, geompy.MakeCompound(edgesFondFiss))
+      geompy.addToStudyInFather(partitionPeauFissFond, edgesFondC, "edgesFondFiss")
+      
+      if aretesVivesC is None:
+        [edgesInside, edgesOutside, edgesOnside] = extractionOrientee(fillingFaceExterne, partitionPeauFissFond, centreFondFiss, "EDGE", 1.e-3)
+        [facesInside, facesOutside, facesOnside] = extractionOrientee(fillingFaceExterne, partitionPeauFissFond, centreFondFiss, "FACE", 1.e-3)
+      else:
+        [edgesInside, edgesOutside, edgesOnside] = extractionOrienteeMulti(facesDefaut, ifil, partitionPeauFissFond, centreFondFiss, "EDGE", 1.e-3)
+        [facesInside, facesOutside, facesOnside] = extractionOrienteeMulti(facesDefaut, ifil, partitionPeauFissFond, centreFondFiss, "FACE", 1.e-3)
+        
+      edgesPipeIn = geompy.GetSharedShapesMulti([edgesPipeC, geompy.MakeCompound(edgesInside)], geompy.ShapeType["EDGE"])
+      verticesPipePeau = []
+
+      for i, edge in enumerate(edgesPipeIn):
+        try:
+          vertices = geompy.GetSharedShapesMulti([edge, geompy.MakeCompound(facesOnside)], geompy.ShapeType["VERTEX"])
+          verticesPipePeau.append(vertices[0])
+          name = "edgePipeIn%d"%i
+          geompy.addToStudyInFather(partitionPeauFissFond, edge, name)
+          name = "verticePipePeau%d"%i
+          geompy.addToStudyInFather(partitionPeauFissFond, vertices[0], name)
+          logging.debug("edgePipeIn%s coupe les faces OnSide", i)
+        except:
+          logging.debug("edgePipeIn%s ne coupe pas les faces OnSide", i)
+      edgesFondOut = []
+      edgesFondIn =[]
+      if len(verticesPipePeau) > 0: # au moins une extrémité du pipe sur cette face de peau  
+        tmp = geompy.GetSharedShapesMulti([edgesFondC, geompy.MakeCompound(edgesOutside)], geompy.ShapeType["EDGE"])
+        edgesFondOut = [ ed for ed in tmp if geompy.MinDistance(ed, geompy.MakeCompound(facesOnside)) < 1.e-3]
+        tmp = geompy.GetSharedShapesMulti([edgesFondC, geompy.MakeCompound(edgesInside)], geompy.ShapeType["EDGE"])
+        edgesFondIn = [ ed for ed in tmp if geompy.MinDistance(ed, geompy.MakeCompound(facesOnside)) < 1.e-3]
+      verticesEdgesFondIn = [] # les points du fond de fissure au débouché du pipe sur la peau (indice de edgesFondIn)
+      pipexts = []             # les segments de pipe associés au points de fond de fissure débouchants (même indice)
+      cercles = []             # les cercles de generation des pipes débouchant (même indice)
+      facesFissExt = []        # les faces de la fissure externe associés au points de fond de fissure débouchants (même indice)
+      edgesFissExtPeau = []    # edges des faces de fissure externe sur la peau (même indice)
+      edgesFissExtPipe = []    # edges des faces de fissure externe sur le pipe (même indice)
+      #logging.debug("edgesFondIn %s", edgesFondIn)
+
+      edgesFondFiss, edgesIdByOrientation = orderEdgesFromWire(wireFondFiss)
+      for i,edge in enumerate(edgesFondFiss):
+        geompy.addToStudyInFather(wireFondFiss, edge, "edgeFondFiss%d"%i)
+
+      for iedf, edge in enumerate(edgesFondIn):
+        name = "edgeFondIn%d"%iedf
+        geompy.addToStudyInFather(partitionPeauFissFond, edge, name)
+        dist = [ geompy.MinDistance(pt, edge) for pt in verticesPipePeau]
+        ptPeau = verticesPipePeau[dist.index(min(dist))] # le point de verticesPipePeau a distance minimale de l'edge
+        [u, PointOnEdge, EdgeInWireIndex]  = geompy.MakeProjectionOnWire(ptPeau, wireFondFiss)
+        logging.debug("u:%s, EdgeInWireIndex: %s, len(edgesFondFiss): %s", u, EdgeInWireIndex, len(edgesFondFiss))
+        localEdgeInFondFiss = edgesFondFiss[EdgeInWireIndex]
+        centre = PointOnEdge
+        centre2 = geompy.MakeVertexOnCurve(localEdgeInFondFiss, u)
+        geompy.addToStudyInFather(partitionPeauFissFond, centre2, "centre2_%d"%iedf)
+        verticesEdgesFondIn.append(centre)
+        name = "verticeEdgesFondIn%d"%iedf
+        geompy.addToStudyInFather(partitionPeauFissFond, centre, name)
+        norm = geompy.MakeTangentOnCurve(localEdgeInFondFiss, u)
+        geompy.addToStudyInFather(partitionPeauFissFond, centre, "norm%d"%iedf)
+        cercle = geompy.MakeCircle(centre, norm, rayonPipe)
+        geompy.addToStudyInFather(partitionPeauFissFond, cercle, "cerclorig%d"%iedf)
+        [vertex] = geompy.ExtractShapes(cercle, geompy.ShapeType["VERTEX"], False)
+        vec1 = geompy.MakeVector(centre, vertex)
+        vec2 = geompy.MakeVector(centre, ptPeau)
+        angle = geompy.GetAngleRadians(vec1, vec2)
+        # cas général : on reconstitue une portion de pipe, avec l'arête de couture qui coincide
+        #   avec la face de fissure, au niveau du débouché sur la face externe
+        # cas dégénéré : le pipe débouche perpendiculairement à une surface plane à l'origine.
+        #   La partition filling / pipe reconstruit échoue.
+        #   - Si on partitionne le filling avec un simple pipe obtenu par extrusion droite du cercle,
+        #     cela donne un point en trop sur le cercle.
+        #   - Si on prend une vraie surface plane (pas un filling), on peut faire la partition avec 
+        #     les pipes reconstruits              
+        logging.debug("angle=%s", angle)
+        #if abs(angle) > 1.e-7:
+        sommetAxe = geompy.MakeTranslationVector(centre, norm)
+        pm = produitMixte(centre, vertex, ptPeau, sommetAxe)
+        if pm > 0:  # ajout de pi a (-)angle pour éviter des points confondus (partition échoue) dans les cas dégénérés
+          cercle = geompy.MakeRotation(cercle, norm, angle + math.pi)
+        else:
+          cercle = geompy.MakeRotation(cercle, norm, -angle + math.pi)
+        name = "cercle%d"%iedf
+        geompy.addToStudyInFather(partitionPeauFissFond, cercle, name)
+        cercles.append(cercle)
+
+        # --- estimation de la longueur du pipe necessaire de part et d'autre du point de sortie
+        if aretesVivesC is None:
+          faceTestPeau = fillingFaceExterne
+        else:
+          faceTestPeau = facesDefaut[ifil]
+        sideCentre = whichSide(faceTestPeau, centre)
+        locPt0 = geompy.MakeVertexOnCurve(localEdgeInFondFiss, 0.0)
+        locPt1 = geompy.MakeVertexOnCurve(localEdgeInFondFiss, 1.0)
+        sidePt0 = whichSide(faceTestPeau, locPt0)
+        sidePt1 = whichSide(faceTestPeau, locPt1)
+        logging.debug("position centre cercle: %s, extremité edge u0: %s, u1: %s", sideCentre, sidePt0, sidePt1) 
+        normFace = geompy.GetNormal(faceTestPeau, ptPeau)
+        inclPipe = abs(geompy.GetAngleRadians(norm, normFace))
+        lgp = max(rayonPipe/2., abs(3*rayonPipe*math.tan(inclPipe)))
+        logging.debug("angle inclinaison Pipe en sortie: %s degres, lgp: %s", inclPipe*180/math.pi, lgp)
+        
+        # --- position des points extremite du pipe sur l'edge debouchante
+        #     il faut la distance curviligne ofp du point central par rapport à une extrémité de l'edge débouchante
+        locEdgePart = geompy.MakePartition([localEdgeInFondFiss],[centre], [], [], geompy.ShapeType["EDGE"], 0, [], 0)
+        edgesLoc = geompy.ExtractShapes(locEdgePart, geompy.ShapeType["EDGE"], False)
+        edgesLocSorted =[(geompy.MinDistance(edge, locPt0), kk, edge) for kk, edge in enumerate(edgesLoc)]
+        edgesLocSorted.sort()
+        ofp = geompy.BasicProperties(edgesLocSorted[0][2])[0] # distance curviligne centre locPt0
+        logging.debug("distance curviligne centre extremite0: %s", ofp)
+        p1 = geompy.MakeVertexOnCurveByLength(localEdgeInFondFiss, ofp +lgp, locPt0)
+        p2 = geompy.MakeVertexOnCurveByLength(localEdgeInFondFiss, ofp -lgp, locPt0)
+        geompy.addToStudyInFather(wireFondFiss, p1, "p1_%d"%iedf)
+        geompy.addToStudyInFather(wireFondFiss, p2, "p2_%d"%iedf)
+
+        edgePart = geompy.MakePartition([localEdgeInFondFiss], [p1,p2], [], [], geompy.ShapeType["EDGE"], 0, [], 0)
+        edps = geompy.ExtractShapes(edgePart, geompy.ShapeType["EDGE"], True)
+        for edp in edps:
+          if geompy.MinDistance(centre, edp) < 1.e-3:
+            pipext = geompy.MakePipe(cercle, edp)
+            name = "pipeExt%d"%iedf
+            geompy.addToStudyInFather(partitionPeauFissFond, pipext, name)
+            pipexts.append(pipext)
+
+        for face in facesInside:
+          logging.debug("recherche edges communes entre une face inside et (faces onside, edges pipe et fond débouchante)")
+          edgesPeauFis = []
+          edgesPipeFis = []
+          edgesPipeFnd = []
+          try:
+            edgesPeauFis = geompy.GetSharedShapesMulti([geompy.MakeCompound(facesOnside), face], geompy.ShapeType["EDGE"])
+            logging.debug("    faces onside %s",edgesPeauFis)
+            edgesPipeFis = geompy.GetSharedShapesMulti([geompy.MakeCompound(edgesPipeIn), face], geompy.ShapeType["EDGE"])
+            logging.debug("    edgesPipeIn %s", edgesPipeFis)
+            edgesPipeFnd = geompy.GetSharedShapesMulti([geompy.MakeCompound(edgesFondIn), face], geompy.ShapeType["EDGE"])
+            logging.debug("    edgesFondIn %s ", edgesPipeFnd)
+          except:
+            logging.debug("  pb edges communes %s %s %s",edgesPeauFis, edgesPipeFis, edgesPipeFnd)
+            pass
+          if (len(edgesPeauFis) > 0) and (len(edgesPipeFis) > 0) and (len(edgesPipeFnd) == 0):
+            dist = geompy.MinDistance(geompy.MakeCompound(edgesPeauFis), ptPeau)
+            logging.debug("    test distance extrémité reference %s", dist)
+            if dist < 1.e-3: # c'est la face de fissure externe associée
+              logging.debug("    face %s inside ajoutée", i)
+              facesFissExt.append(face)
+              name="faceFissExt%d"%iedf
+              geompy.addToStudyInFather(partitionPeauFissFond, face, name)
+              dist = 1.
+              for ipe, edpe in enumerate(edgesPeauFis):
+                for ipi, edpi in enumerate(edgesPipeFis):
+                  dist = geompy.MinDistance(edpe, edpi)
+                  if dist < 1.e-3:
+                    edgesFissExtPeau.append(edpe)
+                    name="edgesFissExtPeau%d"%iedf
+                    geompy.addToStudyInFather(partitionPeauFissFond, edpe, name)
+                    edgesFissExtPipe.append(edpi)
+                    name="edgesFissExtPipe%d"%iedf
+                    geompy.addToStudyInFather(partitionPeauFissFond, edpi, name)
+                    break
+                if dist < 1.e-3:
+                  break
+
+      if len(verticesPipePeau) == 0: # aucune extrémité du pipe sur cette face de peau
+                                     # il faut recenser les edges de fissure sur la face de peau
+        j = 0
+        for face in facesInside:
+          edgesPeauFis = []
+          edgesPipeFis = []
+          edgesPipeFnd = []
+          try:
+            edgesPeauFis = geompy.GetSharedShapesMulti([geompy.MakeCompound(facesOnside), face], geompy.ShapeType["EDGE"])
+            edgesPipeFis = geompy.GetSharedShapesMulti([geompy.MakeCompound(edgesPipeIn), face], geompy.ShapeType["EDGE"])
+            edgesPipeFnd = geompy.GetSharedShapesMulti([geompy.MakeCompound(edgesFondIn), face], geompy.ShapeType["EDGE"])
+          except:
+            pass
+          if (len(edgesPeauFis) > 0) and (len(edgesPipeFis) > 0) and (len(edgesPipeFnd) == 0):
+            edgesFissExtPeau.append(edgesPeauFis[0])
+            name="edgesFissExtPeau%d"%j
+            geompy.addToStudyInFather(partitionPeauFissFond, edgesPeauFis[0], name)
+            j += 1
+     
+      # -----------------------------------------------------------------------
+      # --- identification faces de peau : face de peau percée du pipe, extrémités du pipe
+      #     La partition avec le pipe peut créer un vertex (et un edge) de trop sur le cercle projeté,
+      #     quand le cercle est très proche de la face.
+      #     dans ce cas, la projection du cercle sur la face suivie d'une partition permet
+      #     d'éviter le point en trop
+      
+      facesAndFond = facesOnside
+      facesAndFond.append(wireFondFiss)
+      try:
+        partitionPeauByPipe = geompy.MakePartition(facesAndFond, pipexts, [], [], geompy.ShapeType["FACE"], 0, [], 1)
+      except:
+        logging.debug("probleme partition face pipe, contournement avec MakeSection")
+        sections = []
+        for pipext in pipexts:
+          sections.append(geompy.MakeSection(facesOnside[0], pipext))
+        partitionPeauByPipe = geompy.MakePartition(facesAndFond, sections, [], [], geompy.ShapeType["FACE"], 0, [], 1)
+        
+      # contrôle edge en trop sur edges circulaires
+      if len(verticesPipePeau) > 0: # --- au moins une extrémité du pipe sur cette face de peau
+        edgeEnTrop = []
+        outilPart = pipexts
+        facesPeau = geompy.ExtractShapes(partitionPeauByPipe, geompy.ShapeType["FACE"], False)
+        facesPeauSorted, minsur, maxsurf = sortFaces(facesPeau)
+        for i, face in enumerate(facesPeauSorted[:-1]): # on ne teste que la ou les petites faces "circulaires"
+          nbv = geompy.NumberOfEdges(face)
+          logging.debug("nombre d'edges sur face circulaire: %s", nbv)
+          if nbv > 3:
+            edgeEnTrop.append(True) # TODO : distinguer les cas avec deux faces circulaires dont l'une est correcte
+          else:
+            edgeEnTrop.append(False)
+        refaire = sum(edgeEnTrop)
+        if refaire > 0:
+          dc = [(geompy.MinDistance(verticesEdgesFondIn[0], fac), i)  for i, fac in enumerate(facesPeauSorted[:-1])]
+          dc.sort()
+          logging.debug("dc sorted: %s", dc)
+          i0 = dc[0][1] # indice de facesPeauSorted qui correspond à verticesEdgesFondIn[0], donc 0 pour cercles
+          direct = (i0 == 0)
+          for i, bad in enumerate(edgeEnTrop):
+            if direct:
+              j = i
+            else:
+              j = 1-i
+            if bad:
+              outilPart[j] = geompy.MakeProjection(cercles[j],facesOnside[0])
+            pass
+          partitionPeauByPipe = geompy.MakePartition(facesAndFond, outilPart, [], [], geompy.ShapeType["FACE"], 0, [], 1)
+          pass
+          
+      name="partitionPeauByPipe%d"%ifil
+      geompy.addToStudy(partitionPeauByPipe, name)
+      [edgesPeauFondIn, edgesPeauFondOut, edgesPeauFondOn] = extractionOrientee(fillingFaceExterne, partitionPeauByPipe, centreFondFiss, "EDGE", 1.e-3)
+      [facesPeauFondIn, facesPeauFondOut, facesPeauFondOn] = extractionOrientee(fillingFaceExterne, partitionPeauByPipe, centreFondFiss, "FACE", 1.e-3)
+        
+      if len(verticesPipePeau) > 0: # --- au moins une extrémité du pipe sur cette face de peau
+        facesPeauSorted, minsur, maxsurf = sortFaces(facesPeauFondOn)
+        facePeau = facesPeauSorted[-1] # la plus grande face
+      else:
+        facePeau =geompy.MakePartition(facesPeauFondOn, [], [], [], geompy.ShapeType["FACE"], 0, [], 1)
+      name="facePeau%d"%ifil
+      geompy.addToStudy(facePeau, name)
+      
+      facesPipePeau = [None for i in range(len(edgesFissExtPipe))]
+      endsEdgeFond = [None for i in range(len(edgesFissExtPipe))]
+      edgeRadFacePipePeau = [None for i in range(len(edgesFissExtPipe))]
+      
+      edgesListees = []
+      edgesCircPeau = []
+      verticesCircPeau = []
+      if len(verticesPipePeau) > 0: # --- au moins une extrémité du pipe sur cette face de peau
+        
+        for face in facesPeauSorted[:-1]: # la ou les faces débouchantes, pas la grande face de peau
+          logging.debug("examen face debouchante circulaire")
+          for i,efep in enumerate(edgesFissExtPipe):
+            dist = geompy.MinDistance(face, efep)
+            logging.debug("  distance face circulaire edge %s", dist)
+            if dist < 1e-3:
+              for ik, edpfi in enumerate(edgesPeauFondIn):
+                if geompy.MinDistance(face, edpfi) < 1e-3:
+                  break
+              sharedVertices = geompy.GetSharedShapesMulti([face, edgesPeauFondIn[ik]], geompy.ShapeType["VERTEX"])
+              nameFace = "facePipePeau%d"%i
+              nameVert = "endEdgeFond%d"%i
+              nameEdge = "edgeRadFacePipePeau%d"%i
+              facesPipePeau[i] = face
+              endsEdgeFond[i] = sharedVertices[0]
+              geompy.addToStudy(face, nameFace)
+              geompy.addToStudy(sharedVertices[0], nameVert)
+              edgesFace = geompy.ExtractShapes(face, geompy.ShapeType["EDGE"], True)
+              for edge in edgesFace:
+                if geompy.MinDistance(edge, sharedVertices[0]) < 1e-3:
+                  edgeRadFacePipePeau[i] = edge
+                  geompy.addToStudy(edge, nameEdge)
+                  break
+                pass
+              pass
+            pass
+          pass
+        
+        # --- edges circulaires de la face de peau et points de jonction de la face externe de fissure
+        logging.debug("facesPipePeau: %s", facesPipePeau)
+        edgesCircPeau = [None for i in range(len(facesPipePeau))]
+        verticesCircPeau = [None for i in range(len(facesPipePeau))]        
+        for i,fcirc in enumerate(facesPipePeau):
+          edges = geompy.GetSharedShapesMulti([facePeau, fcirc], geompy.ShapeType["EDGE"])
+          grpEdgesCirc = geompy.CreateGroup(facePeau, geompy.ShapeType["EDGE"])
+          geompy.UnionList(grpEdgesCirc, edges)
+          edgesCircPeau[i] = grpEdgesCirc
+          name = "edgeCirc%d"%i
+          geompy.addToStudyInFather(facePeau, grpEdgesCirc, name)
+          edgesListees = edgesListees + edges
+          vertices = geompy.GetSharedShapesMulti([facePeau, fcirc], geompy.ShapeType["VERTEX"])
+          grpVertCircPeau = geompy.CreateGroup(facePeau, geompy.ShapeType["VERTEX"])
+          geompy.UnionList(grpVertCircPeau, vertices)
+          verticesCircPeau[i] = grpVertCircPeau
+          name = "pointEdgeCirc%d"%i
+          geompy.addToStudyInFather(facePeau, grpVertCircPeau, name)
+          pass
+        pass # --- au moins une extrémité du pipe sur cette face de peau
+
+      # --- edges de bord de la face de peau
+
+      edgesFilling = geompy.ExtractShapes(fillingFaceExterne, geompy.ShapeType["EDGE"], False)
+      edgesBords = []
+      for i, edge in enumerate(edgesFilling):
+        edgepeau = geompy.GetInPlace(facePeau, edge)
+        name = "edgepeau%d"%i
+        geompy.addToStudyInFather(facePeau,edgepeau, name)
+        logging.debug("edgepeau %s", geompy.ShapeInfo(edgepeau))
+        if geompy.ShapeInfo(edgepeau)['EDGE'] > 1:
+          logging.debug("  EDGES multiples")
+          edgs = geompy.ExtractShapes(edgepeau, geompy.ShapeType["EDGE"], False)
+          edgesBords += edgs
+          edgesListees += edgs
+        else:
+          logging.debug("  EDGE")
+          edgesBords.append(edgepeau)
+          edgesListees.append(edgepeau)
+      groupEdgesBordPeau = geompy.CreateGroup(facePeau, geompy.ShapeType["EDGE"])
+      geompy.UnionList(groupEdgesBordPeau, edgesBords)
+      bordsVifs = None
+      if aretesVivesC is not None:
+        bordsVifs = geompy.GetInPlace(facePeau, aretesVivesC)
+      if bordsVifs is not None:
+        geompy.addToStudyInFather(facePeau, bordsVifs, "bordsVifs")
+        groupEdgesBordPeau = geompy.CutGroups(groupEdgesBordPeau, bordsVifs)
+        grptmp = None
+        if len(aretesVivesCoupees) > 0:
+          grpC = geompy.MakeCompound(aretesVivesCoupees)
+          grptmp = geompy.GetInPlace(facePeau, grpC)
+        if grptmp is not None:
+          grpnew = geompy.CutGroups(bordsVifs, grptmp) # ce qui est nouveau dans bordsVifs
+        else:
+          grpnew = bordsVifs
+        if grpnew is not None:
+          edv = geompy.ExtractShapes(grpnew, geompy.ShapeType["EDGE"], False)
+          aretesVivesCoupees += edv
+      logging.debug("aretesVivesCoupees %s",aretesVivesCoupees)
+      geompy.addToStudyInFather(facePeau, groupEdgesBordPeau , "EdgesBords")
+        
+      # ---  edges de la face de peau partagées avec la face de fissure
+      
+      edgesPeau = geompy.ExtractShapes(facePeau, geompy.ShapeType["EDGE"], False)
+      edges = substractSubShapes(facePeau, edgesPeau, edgesListees)
+      edgesFissurePeau = []
+      if len(verticesPipePeau) > 0: # --- au moins une extrémité du pipe sur cette face de peau
+        edgesFissurePeau = [None for i in range(len(verticesCircPeau))] # edges associés aux extrémités du pipe, en premier
+        for edge in edges:
+          for i, grpVert in enumerate(verticesCircPeau):
+            if (geompy.MinDistance(grpVert, edge) < 1.e-3) and (edge not in edgesFissurePeau):
+              edgesFissurePeau[i] = edge
+              name = "edgeFissurePeau%d"%i
+              geompy.addToStudyInFather(facePeau,  edge, name)
+        for edge in edges: # on ajoute après les edges manquantes
+          if edge not in edgesFissurePeau:
+            edgesFissurePeau.append(edge)
+      else:
+        for i, edge in enumerate(edges):
+          edgesFissurePeau.append(edge)
+          name = "edgeFissurePeau%d"%i
+          geompy.addToStudyInFather(facePeau,  edge, name)
+        
+
+      ptEdgeFond[ifil] = endsEdgeFond        # pour chaque face [points edge fond de fissure aux débouchés du pipe]
+      fsPipePeau[ifil] = facesPipePeau       # pour chaque face [faces du pipe débouchantes]
+      edRadFPiPo[ifil] = edgeRadFacePipePeau # pour chaque face [edge radiale des faces du pipe débouchantes ]
+      fsFissuExt[ifil] = facesFissExt        # pour chaque face [faces de fissure externes au pipe]
+      edFisExtPe[ifil] = edgesFissExtPeau    # pour chaque face [edge en peau des faces de fissure externes (pas subshape facePeau)]
+      edFisExtPi[ifil] = edgesFissExtPipe    # pour chaque face [edge commun au pipe des faces de fissure externes]
+      facesPeaux[ifil] = facePeau            # pour chaque face : la face de peau finale a mailler (percee des faces débouchantes)
+      edCircPeau[ifil] = edgesCircPeau       # pour chaque face de peau : [groupe subshapes edges circulaires aux débouchés du pipe]
+      ptCircPeau[ifil] = verticesCircPeau    # pour chaque face de peau : [groupe subshapes points sur edges circulaires aux débouchés du pipe]
+      gpedgeBord[ifil] = groupEdgesBordPeau  # pour chaque face de peau : groupe subshape des edges aux bords liés à la partie saine
+      gpedgeVifs[ifil] = bordsVifs           # pour chaque face de peau : groupe subshape des edges aux bords correspondant à des arêtes vives
+      edFissPeau[ifil] = edgesFissurePeau    # pour chaque face de peau : [subshape edge en peau des faces de fissure externes]
+      ptFisExtPi[ifil] = verticesPipePeau    # pour chaque face de peau : [point commun edFissPeau edCircPeau]
+
+  # -----------------------------------------------------------------------
+  # fin de la boucle sur les faces de filling
+  # -----------------------------------------------------------------------
+  
+  for i, avc in enumerate(aretesVivesCoupees):
+    name = "areteViveCoupee%d"%i
+    geompy.addToStudy(avc, name)
+  
+  # --- identification des faces et edges de fissure externe pour maillage
+  
+  facesFissExt = []
+  edgesFissExtPeau = []
+  edgesFissExtPipe = []
+  for ifil in range(nbFacesFilling): # TODO: éliminer les doublons (comparer tous les vertices triés, avec mesure de distance ?)
+    facesFissExt += fsFissuExt[ifil]
+    edgesFissExtPeau += edFisExtPe[ifil]
+    edgesFissExtPipe += edFisExtPi[ifil]
+  logging.debug("---------------------------- identification faces de fissure externes au pipe :%s ", len(facesFissExt))
+  # regroupement des faces de fissure externes au pipe.
+  
+  if len(facesFissExt) > 1:
+    faceFissureExterne = geompy.MakePartition(facesFissExt, [], [], [], geompy.ShapeType["FACE"], 0, [], 0)
+    edgesPipeFissureExterneC = geompy.GetInPlace(faceFissureExterne, geompy.MakeCompound(edgesPipeFiss))    # edgesFissExtPipe peut ne pas couvrir toute la longueur
+    # edgesPeauFissureExterneC = geompy.GetInPlace(faceFissureExterne, geompy.MakeCompound(edgesFissExtPeau))
+    # il peut manquer des edges de faceFissureExterne en contact avec la peau dans edgesFissExtPeau
+    (isDone, closedFreeBoundaries, openFreeBoundaries) = geompy.GetFreeBoundary(faceFissureExterne)
+    edgesBordFFE = []
+    for bound in closedFreeBoundaries:
+      edgesBordFFE += geompy.ExtractShapes(bound, geompy.ShapeType["EDGE"], False)
+    edgesBordFFEid = [ (ed,geompy.GetSubShapeID(faceFissureExterne, ed)) for ed in edgesBordFFE]
+    logging.debug("edgesBordFFEid %s", edgesBordFFEid)
+    edgesPPE = geompy.ExtractShapes(edgesPipeFissureExterneC, geompy.ShapeType["EDGE"], False)
+    edgesPPEid = [ geompy.GetSubShapeID(faceFissureExterne, ed) for ed in edgesPPE]
+    logging.debug("edgesPPEid %s", edgesPPEid)
+    edgesPFE = [ edid[0] for edid in edgesBordFFEid if edid[1] not in edgesPPEid] # on garde toutes les edges de bord non en contact avec le pipe
+    logging.debug("edgesPFE %s", edgesPFE)
+    edgesPeauFissureExterneC = geompy.MakeCompound(edgesPFE)
+  else:
+    faceFissureExterne = facesFissExt[0]
+    edgesPeauFissureExterneC = geompy.MakeCompound(edgesFissExtPeau)
+    edgesPipeFissureExterneC = geompy.MakeCompound(edgesFissExtPipe)
+  wirePipeFissureExterne = geompy.MakeWire(geompy.ExtractShapes(edgesPipeFissureExterneC, geompy.ShapeType["EDGE"], False))
+  geompy.addToStudy(faceFissureExterne, "faceFissureExterne")
+  geompy.addToStudyInFather(faceFissureExterne, edgesPeauFissureExterneC, "edgesPeauFissureExterne")
+  geompy.addToStudyInFather(faceFissureExterne, edgesPipeFissureExterneC, "edgesPipeFissureExterne")
+  
+  logging.debug("---------------------------- Preparation Maillage du Pipe --------------")
+  # -----------------------------------------------------------------------
+  # --- preparation maillage du pipe :
+  #     - détections des points a respecter : jonction des edges/faces constituant
+  #       la face de fissure externe au pipe
+  #     - points sur les edges de fond de fissure et edges pipe/face fissure,
+  #     - vecteurs tangents au fond de fissure (normal au disque maillé)
+
+  # --- option de maillage selon le rayon de courbure du fond de fissure 
+  lenEdgeFondExt = 0
+  for edff in edgesFondFiss:
+    lenEdgeFondExt += geompy.BasicProperties(edff)[0]
+  
+  disfond = []
+  for filling in facesDefaut:
+    disfond.append(geompy.MinDistance(centreFondFiss, filling))
+  disfond.sort()
+  rcourb = disfond[0]
+  nbSegQuart = 5 # on veut 5 segments min sur un quart de cercle
+  alpha = math.pi/(4*nbSegQuart)
+  deflexion = rcourb*(1.0 -math.cos(alpha))
+  lgmin = lenSegPipe*0.25
+  lgmax = lenSegPipe*1.5               
+  logging.debug("rcourb: %s, lenFond:%s, deflexion: %s, lgmin: %s, lgmax: %s", rcourb, lenEdgeFondExt, deflexion, lgmin, lgmax)  
+
+  meshFondExt = smesh.Mesh(wireFondFiss)
+  algo1d = meshFondExt.Segment()
+  hypo1d = algo1d.Adaptive(lgmin, lgmax, deflexion) # a ajuster selon la profondeur de la fissure
+  isDone = meshFondExt.Compute()
+  
+  ptGSdic = {} # dictionnaire [paramètre sur la courbe] --> point géométrique
+  allNodeIds = meshFondExt.GetNodesId()
+  for nodeId in allNodeIds:
+    xyz = meshFondExt.GetNodeXYZ(nodeId)
+    #logging.debug("nodeId %s, coords %s", nodeId, str(xyz))
+    pt = geompy.MakeVertex(xyz[0], xyz[1], xyz[2])
+    u, PointOnEdge, EdgeInWireIndex = geompy.MakeProjectionOnWire(pt, wireFondFiss) # u compris entre 0 et 1
+    edgeOrder = edgesIdByOrientation[EdgeInWireIndex]
+    ptGSdic[(edgeOrder, EdgeInWireIndex, u)] = pt
+    #logging.debug("nodeId %s, u %s", nodeId, str(u))
+  usort = sorted(ptGSdic)  
+  logging.debug("nombre de points obtenus par deflexion %s",len(usort))
+     
+  centres = []
+  origins = []
+  normals = []      
+  for edu in usort:
+    ied = edu[1]
+    u = edu[2]
+    vertcx = ptGSdic[edu]
+    norm = geompy.MakeTangentOnCurve(edgesFondFiss[ied], u)
+    plan = geompy.MakePlane(vertcx, norm, 3*rayonPipe)
+    part = geompy.MakePartition([plan], [wirePipeFiss], [], [], geompy.ShapeType["VERTEX"], 0, [], 0)
+    liste = geompy.ExtractShapes(part, geompy.ShapeType["VERTEX"], True)
+    if len(liste) == 5: # 4 coins du plan plus intersection recherchée
+      for point in liste:
+        if geompy.MinDistance(point, vertcx) < 1.1*rayonPipe: # les quatre coins sont plus loin
+          vertpx = point
+          break
+      centres.append(vertcx)
+      origins.append(vertpx)
+      normals.append(norm)
+#      name = "vertcx%d"%i
+#      geompy.addToStudyInFather(wireFondFiss, vertcx, name)
+#      name = "vertpx%d"%i
+#      geompy.addToStudyInFather(wireFondFiss, vertpx, name)
+#      name = "plan%d"%i
+#      geompy.addToStudyInFather(wireFondFiss, plan, name)
+
+  # --- maillage du pipe étendu, sans tenir compte de l'intersection avec la face de peau
+      
+  logging.debug("nbsegCercle %s", nbsegCercle)
+  
+  # -----------------------------------------------------------------------
+  # --- points géométriques
+  
+  gptsdisks = [] # vertices géométrie de tous les disques
+  raydisks = [[] for i in range(nbsegCercle)]
+  for i in range(len(centres)): # boucle sur les disques
+    gptdsk = [] # vertices géométrie d'un disque
+    vertcx = centres[i]
+    vertpx = origins[i]
+    normal = normals[i]
+    vec1 = geompy.MakeVector(vertcx, vertpx)
+    
+    points = [vertcx] # les points du rayon de référence
+    for j in range(nbsegRad):
+      pt = geompy.MakeTranslationVectorDistance(vertcx, vec1, (j+1)*float(rayonPipe)/nbsegRad)
+      points.append(pt)
+    gptdsk.append(points)
+    pt = geompy.MakeTranslationVectorDistance(vertcx, vec1, 1.5*rayonPipe)
+    rayon = geompy.MakeLineTwoPnt(vertcx, pt)
+    raydisks[0].append(rayon)
+    
+    for k in range(nbsegCercle-1):
+      angle = (k+1)*2*math.pi/nbsegCercle
+      pts = [vertcx] # les points d'un rayon obtenu par rotation
+      for j in range(nbsegRad):
+        pt = geompy.MakeRotation(points[j+1], normal, angle)
+        pts.append(pt)
+      gptdsk.append(pts)
+      ray = geompy.MakeRotation(rayon, normal, angle)
+      raydisks[k+1].append(ray)
+      
+    gptsdisks.append(gptdsk) 
+  # -----------------------------------------------------------------------
+  # --- recherche des points en trop (externes au volume à remailler)
+  #     - on associe chaque extrémité du pipe à une face filling 
+  #     - on part des disques aux extrémités du pipe
+  #     - pour chaque disque, on prend les vertices de géométrie,
+  #       on marque leur position relative à la face.
+  #     - on s'arrete quand tous les noeuds sont dedans
+  
+  logging.debug("---------------------------- recherche des points du pipe a éliminer --------------")
+
+  pt0 = centres[0]
+  pt1 = centres[-1]
+  idFillingFromBout = [None, None]                 # contiendra l'index du filling pour les extrémités 0 et 1
+  for ifil in range(nbFacesFilling):
+    for ipt, pt in enumerate(ptEdgeFond[ifil]): # il y a un ou deux points débouchant sur cette face
+      if geompy.MinDistance(pt,pt0) < geompy.MinDistance(pt,pt1): # TODO: trouver plus fiable pour les cas tordus...
+        idFillingFromBout[0] = ifil
+      else: 
+        idFillingFromBout[1] = ifil
+  logging.debug("association bouts du pipe - faces de filling: %s", idFillingFromBout)
+  
+  facesPipePeau = []
+  edgeRadFacePipePeau = []
+  for ifil in range(nbFacesFilling):
+    facesPipePeau += fsPipePeau[ifil]
+    edgeRadFacePipePeau += edRadFPiPo[ifil]
+    
+  logging.debug("recherche des disques de noeuds complètement internes")
+  idisklim = [] # indices des premier et dernier disques internes
+  idiskout = [] # indices des premier et dernier disques externes
+  for bout in range(2):
+    if bout == 0:
+      idisk = -1
+      inc = 1
+      numout = -1
+    else:
+      idisk = len(gptsdisks)
+      inc = -1
+      numout = len(gptsdisks)
+    inside = False
+    outside = True
+    while not inside:
+      idisk = idisk + inc
+      logging.debug("examen disque %s", idisk)
+      gptdsk = gptsdisks[idisk]
+      inside = True
+      for k in range(nbsegCercle):
+        points = gptdsk[k]
+        for j, pt in enumerate(points):
+          side = whichSideVertex(facesDefaut[idFillingFromBout[bout]], pt)
+          if side < 0:
+            if outside: # premier point detecté dedans
+              outside = False
+              numout = idisk -inc # le disque précédent était dehors
+          else:
+            inside = False # ce point est dehors              
+        if not inside and not outside:
+          break
+    idisklim.append(idisk)  # premier et dernier disques internes
+    idiskout.append(numout) # premier et dernier disques externes
+    
+  # --- listes de nappes radiales en filling à chaque extrémité débouchante
+  facesDebouchantes = [False, False]
+  idFacesDebouchantes = [-1, -1] # contiendra les indices des faces disque débouchantes (facesPipePeau)
+  listNappes =[]
+  for i, idisk in enumerate(idisklim):
+    numout = idiskout[i]
+    logging.debug("extremité %s, indices disques interne %s, externe %s",i, idisk, numout)
+    nappes = []
+    if  (idisk != 0) and (idisk != len(gptsdisks)-1): # si extrémité débouchante
+      for k in range(nbsegCercle):
+        if i == 0:
+          iddeb = max(0, numout)
+          idfin = max(iddeb+3,idisk+1) # il faut 3 rayons pour faire un filling qui suive le fond de fissure
+          #logging.debug("extremité %s, indices retenus interne %s, externe %s",i, idfin, iddeb)
+          comp = geompy.MakeCompound(raydisks[k][iddeb:idfin])
+          name='compoundRay%d'%k
+          geompy.addToStudy(comp, name)
+        else:
+          idfin = min(len(gptsdisks), numout+1)
+          iddeb = min(idfin-3, idisk) # il faut 3 rayons pour faire un filling qui suive le fond de fissure
+          #logging.debug("extremité %s, indices retenus interne %s, externe %s",i, idfin, iddeb)
+          comp = geompy.MakeCompound(raydisks[k][iddeb:idfin])
+          name='compoundRay%d'%k
+          geompy.addToStudy(comp, name)
+        nappe = geompy.MakeFilling(comp, 2, 5, 0.0001, 0.0001, 0, GEOM.FOM_Default)
+        nappes.append(nappe)
+        name='nappe%d'%k
+        geompy.addToStudy(nappe, name)
+        facesDebouchantes[i] = True
+    listNappes.append(nappes)
+      
+  # --- mise en correspondance avec les indices des faces disque débouchantes (facesPipePeau)
+  for i, nappes in enumerate(listNappes):
+    if facesDebouchantes[i]:
+      for k, face in enumerate(facesPipePeau):
+        edge = geompy.MakeSection(face, nappes[0])
+        if geompy.NbShapes(edge, geompy.ShapeType["EDGE"]) > 0:
+          idFacesDebouchantes[i] = k
+          break
+  logging.debug("idFacesDebouchantes: %s", idFacesDebouchantes)
+
+  # --- construction des listes d'edges radiales sur chaque extrémité débouchante
+  listEdges = []
+  for i, nappes in enumerate(listNappes):
+    id = idFacesDebouchantes[i] # indice de face débouchante (facesPipePeau)
+    if id < 0:
+      listEdges.append([])
+    else:
+      face = facesPipePeau[id]
+      edges = [edgeRadFacePipePeau[id]]
+      for k, nappe in enumerate(nappes):
+        if k > 0:
+          obj = geompy.MakeSection(face, nappes[k]) # normalement une edge, parfois un compound d'edges dont un tout petit
+          edge = obj
+          vs = geompy.ExtractShapes(obj, geompy.ShapeType["VERTEX"], False)
+          if len(vs) > 2:
+            eds = geompy.ExtractShapes(obj, geompy.ShapeType["EDGE"], False)
+            [edsorted, minl,maxl] = sortEdges(eds)
+            edge = edsorted[-1]
+          else:
+            maxl = geompy.BasicProperties(edge)[0]
+          if maxl < 0.01: # problème MakeSection
+            logging.debug("problème MakeSection recherche edge radiale %s, longueur trop faible: %s, utilisation partition", k, maxl)
+            partNappeFace = geompy.MakePartition([face, nappes[k]], [] , [], [], geompy.ShapeType["FACE"], 0, [], 0)
+            edps= geompy.ExtractShapes(partNappeFace, geompy.ShapeType["EDGE"], False)
+            ednouv = []
+            for ii, ed in enumerate(edps):
+              vxs = geompy.ExtractShapes(ed, geompy.ShapeType["VERTEX"], False)
+              distx = [geompy.MinDistance(vx, face) for vx in vxs]
+              distx += [geompy.MinDistance(vx, nappes[k]) for vx in vxs]
+              dmax = max(distx)
+              logging.debug("  dmax %s",dmax)
+              if dmax < 0.01:
+                ednouv.append(ed)
+            logging.debug("  edges issues de la partition: %s", ednouv)
+            for ii, ed in enumerate(ednouv):
+              geompy.addToStudy(ed, "ednouv%d"%ii)
+            [edsorted, minl,maxl] = sortEdges(ednouv)
+            logging.debug("  longueur edge trouvée: %s", maxl) 
+            edge = edsorted[-1]
+          edges.append(edge)
+          name = 'edgeEndPipe%d'%k
+          geompy.addToStudy(edge, name)
+      listEdges.append(edges)
+
+  # --- création des points du maillage du pipe sur la face de peau
+  for i, edges in enumerate(listEdges):
+    id = idFacesDebouchantes[i] # indice de face débouchante (facesPipePeau)
+    if id >= 0:
+      gptdsk = []
+      if id > 0: # id vaut 0 ou 1
+        id = -1  # si id vaut 1, on prend le dernier élément de la liste (1 ou 2 extrémités débouchent sur la face)
+      centre = ptEdgeFond[idFillingFromBout[i]][id]
+      name = "centre%d"%id
+      geompy.addToStudy(centre, name)
+      vertPipePeau = ptFisExtPi[idFillingFromBout[i]][id]
+      geompy.addToStudyInFather(centre, vertPipePeau, "vertPipePeau")
+      grpsEdgesCirc = edCircPeau[idFillingFromBout[i]] # liste de groupes
+      edgesCirc = []
+      for grpEdgesCirc in grpsEdgesCirc:
+        edgesCirc += geompy.ExtractShapes(grpEdgesCirc, geompy.ShapeType["EDGE"], False)
+      for k, edge in enumerate(edges):
+        extrems = geompy.ExtractShapes(edge, geompy.ShapeType["VERTEX"], True)
+        if geompy.MinDistance(centre, extrems[0]) < geompy.MinDistance(centre, extrems[1]):
+          bout = extrems[1]
+        else:
+          bout = extrems[0]
+        # ajustement du point extrémité (bout) sur l'edge circulaire en face de peau
+        logging.debug("edgesCirc: %s", edgesCirc)
+        distEdgeCirc = [(geompy.MinDistance(bout, edgeCirc), k2, edgeCirc) for k2, edgeCirc in enumerate(edgesCirc)]
+        distEdgeCirc.sort()
+        logging.debug("distEdgeCirc: %s", distEdgeCirc)
+        u = projettePointSurCourbe(bout, distEdgeCirc[0][2])
+        if (abs(u) < 0.02) or (abs(1-u) < 0.02): # les points très proches d'une extrémité doivent y être mis précisément.
+          extrCircs = geompy.ExtractShapes(distEdgeCirc[0][2], geompy.ShapeType["VERTEX"], True)
+          if geompy.MinDistance(bout, extrCircs[0]) < geompy.MinDistance(bout, extrCircs[1]):
+            bout = extrCircs[0]
+          else:
+            bout = extrCircs[1]
+          pass
+        else:
+          bout = geompy.MakeVertexOnCurve(distEdgeCirc[0][2], u)
+        name ="bout%d"%k
+        geompy.addToStudyInFather(centre, bout, name)
+        # enregistrement des points dans la structure
+        points = []
+        for j in range(nbsegRad +1):
+          u = j/float(nbsegRad)
+          points.append(geompy.MakeVertexOnCurve(edge, u))
+        if geompy.MinDistance(bout, points[0]) < geompy.MinDistance(centre, points[0]):
+          points.reverse()
+        points[0] = centre
+        points[-1] = bout
+        gptdsk.append(points)
+      if i == 0:
+        gptsdisks[idisklim[0] -1] = gptdsk
+        idisklim[0] = idisklim[0] -1
+      else:
+        gptsdisks[idisklim[1] +1] = gptdsk
+        idisklim[1] = idisklim[1] +1
+
+  # --- ajustement precis des points sur edgesPipeFissureExterneC
+  
+  edgesPFE = geompy.ExtractShapes(edgesPipeFissureExterneC, geompy.ShapeType["EDGE"], False)
+  verticesPFE = findWireIntermediateVertices(wirePipeFissureExterne)  # vertices intermédiaires (des points en trop dans ptsInWireFissExtPipe)
+  idiskmin = idisklim[0] + 1 # on ne prend pas le disque sur la peau, déjà ajusté
+  idiskmax = idisklim[1]     # on ne prend pas le disque sur la peau, déjà ajusté
+  idiskint = []
+  for vtx in verticesPFE:
+    distPtVt = []
+    for idisk in range(idiskmin, idiskmax):
+      gptdsk = gptsdisks[idisk]
+      pt = gptdsk[0][-1]       # le point sur l'edge de la fissure externe au pipe
+      distPtVt.append((geompy.MinDistance(pt, vtx), idisk))
+    distPtVt.sort()
+    idiskint.append(distPtVt[0][1])
+    gptsdisks[idiskint[-1]][0][-1] = vtx
+    logging.debug("ajustement point sur edgePipeFissureExterne, vertex: %s %s", idiskint[-1], distPtVt[0][0])
+  for idisk in range(idiskmin, idiskmax):
+    if idisk in idiskint:
+      break
+    logging.debug("ajustement point sur edgePipeFissureExterne: %s", idisk)
+    gptdsk = gptsdisks[idisk]
+    pt = gptdsk[0][-1]       # le point sur l'edge de la fissure externe au pipe
+    distPtEd = [(geompy.MinDistance(pt, edgePFE), k, edgePFE) for k, edgePFE in enumerate(edgesPFE)]
+    distPtEd.sort()
+    edgePFE = distPtEd[0][2]
+    u = projettePointSurCourbe(pt, edgePFE)
+    ptproj = geompy.MakeVertexOnCurve(edgePFE, u)
+    gptsdisks[idisk][0][-1] = ptproj
+  
+  # -----------------------------------------------------------------------
+  # --- maillage effectif du pipe
+
+  logging.debug("---------------------------- maillage effectif du pipe --------------")
+  meshPipe = smesh.Mesh(None, "meshPipe")
+  fondFissGroup = meshPipe.CreateEmptyGroup(SMESH.EDGE, "FONDFISS")
+  nodesFondFissGroup = meshPipe.CreateEmptyGroup(SMESH.NODE, "nfondfis")
+  faceFissGroup = meshPipe.CreateEmptyGroup(SMESH.FACE, "fisInPi")
+  edgeFaceFissGroup = meshPipe.CreateEmptyGroup(SMESH.EDGE, "edgeFaceFiss")
+  edgeCircPipe0Group = meshPipe.CreateEmptyGroup(SMESH.EDGE, "edgeCircPipe0")
+  edgeCircPipe1Group = meshPipe.CreateEmptyGroup(SMESH.EDGE, "edgeCircPipe1")
+  faceCircPipe0Group = meshPipe.CreateEmptyGroup(SMESH.FACE, "faceCircPipe0")
+  faceCircPipe1Group = meshPipe.CreateEmptyGroup(SMESH.FACE, "faceCircPipe1")
+  mptsdisks = []  # vertices maillage de tous les disques
+  mEdges = []     # identifiants edges maillage fond de fissure
+  mEdgeFaces = [] # identifiants edges maillage edge face de fissure externe
+  mFaces = []     # identifiants faces maillage fissure
+  mVols  = []     # identifiants volumes maillage pipe
+
+  mptdsk = None
+  for idisk in range(idisklim[0], idisklim[1]+1): # boucle sur les disques internes
+    
+    # -----------------------------------------------------------------------
+    # --- points
+    
+    gptdsk = gptsdisks[idisk]
+    if idisk > idisklim[0]:
+      oldmpts = mptdsk
+    mptdsk = [] # vertices maillage d'un disque
+    for k in range(nbsegCercle):
+      points = gptdsk[k]
+      mptids = []
+      for j, pt in enumerate(points):
+        if j == 0 and k > 0:
+          id = mptdsk[0][0]
+        else:
+          coords = geompy.PointCoordinates(pt)
+          id = meshPipe.AddNode(coords[0], coords[1], coords[2])
+        mptids.append(id)
+      mptdsk.append(mptids)
+    mptsdisks.append(mptdsk)
+    
+    # -----------------------------------------------------------------------
+    # --- groupes edges cercles debouchants
+    
+    if idisk == idisklim[0]:
+      pts = []
+      for k in range(nbsegCercle):
+        pts.append(mptdsk[k][-1])
+      edges = []
+      for k in range(len(pts)):
+        k1 = (k+1)%len(pts)
+        idEdge = meshPipe.AddEdge([pts[k], pts[k1]])
+        edges.append(idEdge)
+      edgeCircPipe0Group.Add(edges)
+       
+    if idisk == idisklim[1]:
+      pts = []
+      for k in range(nbsegCercle):
+        pts.append(mptdsk[k][-1])
+      edges = []
+      for k in range(len(pts)):
+        k1 = (k+1)%len(pts)
+        idEdge = meshPipe.AddEdge([pts[k], pts[k1]])
+        edges.append(idEdge)
+      edgeCircPipe1Group.Add(edges)
+    
+    # -----------------------------------------------------------------------
+    # --- groupes faces  debouchantes
+    
+    if idisk == idisklim[0]:
+      faces = []
+      for j in range(nbsegRad):
+        for k in range(nbsegCercle):
+          k1 = k+1
+          if k ==  nbsegCercle-1:
+            k1 = 0
+          if j == 0:
+            idf = meshPipe.AddFace([mptdsk[k][0], mptdsk[k][1], mptdsk[k1][1]]) # triangle
+          else:
+            idf = meshPipe.AddFace([mptdsk[k][j], mptdsk[k][j+1], mptdsk[k1][j+1], mptdsk[k1][j]]) # quadrangle
+          faces.append(idf)
+      faceCircPipe0Group.Add(faces)
+
+    if idisk == idisklim[1]:
+      faces = []
+      for j in range(nbsegRad):
+        for k in range(nbsegCercle):
+          k1 = k+1
+          if k ==  nbsegCercle-1:
+            k1 = 0
+          if j == 0:
+            idf = meshPipe.AddFace([mptdsk[k][0], mptdsk[k][1], mptdsk[k1][1]]) # triangle
+          else:
+            idf = meshPipe.AddFace([mptdsk[k][j], mptdsk[k][j+1], mptdsk[k1][j+1], mptdsk[k1][j]]) # quadrangle
+          faces.append(idf)
+      faceCircPipe1Group.Add(faces)
+          
+    # -----------------------------------------------------------------------
+    # --- mailles volumiques, groupes noeuds et edges de fond de fissure, groupe de face de fissure
+    
+    if idisk == idisklim[0]:
+      mEdges.append(0)
+      mEdgeFaces.append(0)
+      mFaces.append([0])
+      mVols.append([[0]])
+      nodesFondFissGroup.Add([mptdsk[0][0]])
+    else:
+      ide = meshPipe.AddEdge([oldmpts[0][0], mptdsk[0][0]])
+      mEdges.append(ide)
+      fondFissGroup.Add([ide])
+      nodesFondFissGroup.Add([mptdsk[0][0]])
+      ide2 = meshPipe.AddEdge([oldmpts[0][-1], mptdsk[0][-1]])
+      mEdgeFaces.append(ide2)
+      edgeFaceFissGroup.Add([ide2])
+      idFaces = []
+      idVols = []
+      
+      for j in range(nbsegRad):
+        idf = meshPipe.AddFace([oldmpts[0][j], mptdsk[0][j], mptdsk[0][j+1], oldmpts[0][j+1]])
+        faceFissGroup.Add([idf])
+        idFaces.append(idf)
+        
+        idVolCercle = []
+        for k in range(nbsegCercle):
+          k1 = k+1
+          if k ==  nbsegCercle-1:
+            k1 = 0
+          if j == 0:
+            idv = meshPipe.AddVolume([mptdsk[k][j], mptdsk[k][j+1], mptdsk[k1][j+1],
+                                      oldmpts[k][j], oldmpts[k][j+1], oldmpts[k1][j+1]])
+          else:
+            idv = meshPipe.AddVolume([mptdsk[k][j], mptdsk[k][j+1], mptdsk[k1][j+1], mptdsk[k1][j],
+                                      oldmpts[k][j], oldmpts[k][j+1], oldmpts[k1][j+1], oldmpts[k1][j]])
+          idVolCercle.append(idv)
+        idVols.append(idVolCercle)  
+        
+      mFaces.append(idFaces)
+      mVols.append(idVols)
+
+  pipeFissGroup = meshPipe.CreateEmptyGroup( SMESH.VOLUME, 'PIPEFISS' )
+  nbAdd = pipeFissGroup.AddFrom( meshPipe.GetMesh() )
+
+  nb, new_mesh, new_group = meshPipe.MakeBoundaryElements(SMESH.BND_2DFROM3D, "pipeBoundaries")
+  edgesCircPipeGroup = [edgeCircPipe0Group, edgeCircPipe1Group]
+
+  # --- fin du maillage du pipe
+  # -----------------------------------------------------------------------
+  # --- edges de bord, faces défaut à respecter
+
+  aFilterManager = smesh.CreateFilterManager()
+  nbAdded, internalBoundary, _NoneGroup = internalBoundary.MakeBoundaryElements( SMESH.BND_1DFROM2D, '', '', 0, [  ])
+  criteres = []
+  unCritere = smesh.GetCriterion(SMESH.EDGE,SMESH.FT_FreeBorders,SMESH.FT_Undefined,0)
+  criteres.append(unCritere)
+  filtre = smesh.GetFilterFromCriteria(criteres)
+  bordsLibres = internalBoundary.MakeGroupByFilter( 'bords', filtre )
+  smesh.SetName(bordsLibres, 'bordsLibres')
+
+  # --- pour aider l'algo hexa-tetra à ne pas mettre de pyramides à l'exterieur des volumes repliés sur eux-mêmes
+  #     on désigne les faces de peau en quadrangles par le groupe "skinFaces"
+
+  skinFaces = internalBoundary.CreateEmptyGroup( SMESH.FACE, 'skinFaces' )
+  nbAdd = skinFaces.AddFrom( internalBoundary.GetMesh() )
+
+  # --- maillage des éventuelles arêtes vives entre faces reconstruites
+  
+  if len(aretesVivesCoupees) > 0:
+    aretesVivesC = geompy.MakeCompound(aretesVivesCoupees)
+    meshAretesVives = smesh.Mesh(aretesVivesC)
+    algo1d = meshAretesVives.Segment()
+    hypo1d = algo1d.LocalLength(dmoyen/3.0,[],1e-07)
+    putName(algo1d.GetSubMesh(), "aretesVives")
+    putName(algo1d, "algo1d_aretesVives")
+    putName(hypo1d, "hypo1d_aretesVives")
+    isDone = meshAretesVives.Compute()
+    logging.info("aretesVives fini")
+    grpAretesVives = meshAretesVives.CreateEmptyGroup( SMESH.EDGE, 'grpAretesVives' )
+    nbAdd = grpAretesVives.AddFrom( meshAretesVives.GetMesh() )
+
+  # -----------------------------------------------------------------------
+  # --- maillage faces de fissure
+  
+  logging.debug("---------------------------- maillage faces de fissure externes au pipe :%s --------------", len(facesFissExt))
+
+  meshFaceFiss = smesh.Mesh(faceFissureExterne)
+  algo2d = meshFaceFiss.Triangle(algo=smeshBuilder.NETGEN_1D2D)
+  hypo2d = algo2d.Parameters()
+  hypo2d.SetMaxSize( areteFaceFissure )
+  hypo2d.SetSecondOrder( 0 )
+  hypo2d.SetOptimize( 1 )
+  hypo2d.SetFineness( 2 )
+  hypo2d.SetMinSize( rayonPipe/float(nbsegRad) )
+  hypo2d.SetQuadAllowed( 0 )
+  putName(algo2d.GetSubMesh(), "faceFiss")
+  putName(algo2d, "algo2d_faceFiss")
+  putName(hypo2d, "hypo2d_faceFiss")
+  
+  algo1d = meshFaceFiss.UseExisting1DElements(geom=edgesPipeFissureExterneC)
+  hypo1d = algo1d.SourceEdges([ edgeFaceFissGroup ],0,0)
+  putName(algo1d.GetSubMesh(), "edgeFissPeau")
+  putName(algo1d, "algo1d_edgeFissPeau")
+  putName(hypo1d, "hypo1d_edgeFissPeau")
+  
+  isDone = meshFaceFiss.Compute()
+  logging.info("meshFaceFiss fini")
+
+  grpFaceFissureExterne = meshFaceFiss.GroupOnGeom(faceFissureExterne, "fisOutPi", SMESH.FACE)
+  grpEdgesPeauFissureExterne = meshFaceFiss.GroupOnGeom(edgesPeauFissureExterneC,'edgesPeauFissureExterne',SMESH.EDGE)
+  grpEdgesPipeFissureExterne = meshFaceFiss.GroupOnGeom(edgesPipeFissureExterneC,'edgesPipeFissureExterne',SMESH.EDGE)
+
+  # --- maillage faces de peau
+  
+  boutFromIfil = [None for i in range(nbFacesFilling)]
+  if idFillingFromBout[0] != idFillingFromBout[1]: # repérage des extremites du pipe quand elles débouchent sur des faces différentes
+    boutFromIfil[idFillingFromBout[0]] = 0
+    boutFromIfil[idFillingFromBout[1]] = 1
+  
+  logging.debug("---------------------------- maillage faces de peau --------------")
+  meshesFacesPeau = []
+  for ifil in range(nbFacesFilling):
+    meshFacePeau = None
+    if partitionsPeauFissFond[ifil] is None: # face de peau maillage sain intacte
+      
+      # --- edges de bord de la face de filling
+      filling = facesDefaut[ifil]
+      edgesFilling = geompy.ExtractShapes(filling, geompy.ShapeType["EDGE"], False)
+      groupEdgesBordPeau = geompy.CreateGroup(filling, geompy.ShapeType["EDGE"])
+      geompy.UnionList(groupEdgesBordPeau, edgesFilling)
+      geompy.addToStudyInFather(filling, groupEdgesBordPeau , "EdgesBords")
+      
+      meshFacePeau = smesh.Mesh(facesDefaut[ifil])
+      
+      algo1d = meshFacePeau.UseExisting1DElements(geom=groupEdgesBordPeau)
+      hypo1d = algo1d.SourceEdges([ bordsLibres ],0,0)
+      putName(algo1d.GetSubMesh(), "bordsLibres", ifil)
+      putName(algo1d, "algo1d_bordsLibres", ifil)
+      putName(hypo1d, "hypo1d_bordsLibres", ifil)
+      
+    else:
+      
+      facePeau           = facesPeaux[ifil] # pour chaque face : la face de peau finale a mailler (percée des faces débouchantes)
+      edgesCircPeau      = edCircPeau[ifil] # pour chaque face de peau : [subshape edge circulaire aux débouchés du pipe]
+      verticesCircPeau   = ptCircPeau[ifil] # pour chaque face de peau : [subshape point sur edge circulaire aux débouchés du pipe]
+      groupEdgesBordPeau = gpedgeBord[ifil] # pour chaque face de peau : groupe subshape des edges aux bords liés à la partie saine
+      bordsVifs          = gpedgeVifs[ifil] # pour chaque face de peau : groupe subshape des edges aux bords correspondant à des arêtes vives
+      edgesFissurePeau   = edFissPeau[ifil] # pour chaque face de peau : [subshape edge en peau des faces de fissure externes]
+
+      meshFacePeau = smesh.Mesh(facePeau)
+      
+      algo1d = meshFacePeau.UseExisting1DElements(geom=groupEdgesBordPeau)
+      hypo1d = algo1d.SourceEdges([ bordsLibres ],0,0)
+      putName(algo1d.GetSubMesh(), "bordsLibres", ifil)
+      putName(algo1d, "algo1d_bordsLibres", ifil)
+      putName(hypo1d, "hypo1d_bordsLibres", ifil)
+      
+      algo1d = meshFacePeau.UseExisting1DElements(geom=geompy.MakeCompound(edgesFissurePeau))
+      hypo1d = algo1d.SourceEdges([ grpEdgesPeauFissureExterne ],0,0)
+      putName(algo1d.GetSubMesh(), "edgePeauFiss", ifil)
+      putName(algo1d, "algo1d_edgePeauFiss", ifil)
+      putName(hypo1d, "hypo1d_edgePeauFiss", ifil)
+      
+      if bordsVifs is not None:
+        algo1d = meshFacePeau.UseExisting1DElements(geom=bordsVifs)
+        hypo1d = algo1d.SourceEdges([ grpAretesVives ],0,0)
+        putName(algo1d.GetSubMesh(), "bordsVifs", ifil)
+        putName(algo1d, "algo1d_bordsVifs", ifil)
+        putName(hypo1d, "hypo1d_bordsVifs", ifil)
+        
+      for i, edgeCirc in enumerate(edgesCircPeau):
+        if edgeCirc is not None:
+          algo1d = meshFacePeau.UseExisting1DElements(geom=edgeCirc)
+          if boutFromIfil[ifil] is None:
+            hypo1d = algo1d.SourceEdges([ edgesCircPipeGroup[i] ],0,0)
+          else:
+            hypo1d = algo1d.SourceEdges([ edgesCircPipeGroup[boutFromIfil[ifil]] ],0,0)
+          name = "cercle%d"%i
+          putName(algo1d.GetSubMesh(), name, ifil)
+          putName(algo1d, "algo1d_" + name, ifil)
+          putName(hypo1d, "hypo1d_" + name, ifil)
+   
+    algo2d = meshFacePeau.Triangle(algo=smeshBuilder.NETGEN_1D2D)
+    hypo2d = algo2d.Parameters()
+    hypo2d.SetMaxSize( dmoyen )
+    hypo2d.SetOptimize( 1 )
+    hypo2d.SetFineness( 2 )
+    hypo2d.SetMinSize( rayonPipe/float(nbsegRad) )
+    hypo2d.SetQuadAllowed( 0 )
+    putName(algo2d.GetSubMesh(), "facePeau", ifil)
+    putName(algo2d, "algo2d_facePeau", ifil)
+    putName(hypo2d, "hypo2d_facePeau", ifil)
+      
+    isDone = meshFacePeau.Compute()
+    logging.info("meshFacePeau %d fini", ifil)
+    GroupFaces = meshFacePeau.CreateEmptyGroup( SMESH.FACE, "facePeau%d"%ifil )
+    nbAdd = GroupFaces.AddFrom( meshFacePeau.GetMesh() )
+    meshesFacesPeau.append(meshFacePeau)
+
+  # --- regroupement des maillages du défaut
+
+  listMeshes = [internalBoundary.GetMesh(),
+                meshPipe.GetMesh(),
+                meshFaceFiss.GetMesh()]
+  for mp in meshesFacesPeau:
+    listMeshes.append(mp.GetMesh())
+
+  meshBoiteDefaut = smesh.Concatenate(listMeshes, 1, 1, 1e-05,False)
+  # pour aider l'algo hexa-tetra à ne pas mettre de pyramides à l'exterieur des volumes repliés sur eux-mêmes
+  # on désigne les faces de peau en quadrangles par le groupe "skinFaces"
+  group_faceFissOutPipe = None
+  group_faceFissInPipe = None
+  groups = meshBoiteDefaut.GetGroups()
+  for grp in groups:
+    if grp.GetType() == SMESH.FACE:
+      #if "internalBoundary" in grp.GetName():
+      #  grp.SetName("skinFaces")
+      if grp.GetName() == "fisOutPi":
+        group_faceFissOutPipe = grp
+      elif grp.GetName() == "fisInPi":
+        group_faceFissInPipe = grp
+
+  # le maillage NETGEN ne passe pas toujours ==> utiliser GHS3D
+  distene=True
+  if distene:
+    algo3d = meshBoiteDefaut.Tetrahedron(algo=smeshBuilder.GHS3D)
+  else:
+    algo3d = meshBoiteDefaut.Tetrahedron(algo=smeshBuilder.NETGEN)
+    hypo3d = algo3d.MaxElementVolume(1000.0)
+  putName(algo3d.GetSubMesh(), "boiteDefaut")
+  putName(algo3d, "algo3d_boiteDefaut")
+  isDone = meshBoiteDefaut.Compute()
+  putName(meshBoiteDefaut, "boiteDefaut")
+  logging.info("meshBoiteDefaut fini")
+  
+  faceFissure = meshBoiteDefaut.GetMesh().UnionListOfGroups( [ group_faceFissOutPipe, group_faceFissInPipe ], 'FACE1' )
+  maillageSain = enleveDefaut(maillageSain, zoneDefaut, zoneDefaut_skin,
+                              zoneDefaut_internalFaces, zoneDefaut_internalEdges)
+  putName(maillageSain, nomFicSain+"_coupe")
+  extrusionFaceFissure, normfiss = shapeSurFissure(facesPortFissure)
+  maillageComplet = RegroupeSainEtDefaut(maillageSain, meshBoiteDefaut,
+                                         None, None, 'COMPLET', normfiss)
+
+  logging.info("conversion quadratique")
+  maillageComplet.ConvertToQuadratic( 1 )
+  logging.info("groupes")
+  groups = maillageComplet.GetGroups()
+  grps = [ grp for grp in groups if grp.GetName() == 'FONDFISS']
+  fond = maillageComplet.GetMesh().CreateDimGroup( grps, SMESH.NODE, 'FONDFISS' )
+
+  logging.info("réorientation face de fissure FACE1")
+  grps = [ grp for grp in groups if grp.GetName() == 'FACE1']
+  nb = maillageComplet.Reorient2D( grps[0], normfiss, grps[0].GetID(1))
+
+  logging.info("réorientation face de fissure FACE2")
+  plansim = geompy.MakePlane(O, normfiss, 10000)
+  fissnorm = geompy.MakeMirrorByPlane(normfiss, plansim)
+  grps = [ grp for grp in groups if grp.GetName() == 'FACE2']
+  nb = maillageComplet.Reorient2D( grps[0], fissnorm, grps[0].GetID(1))
+  fond = maillageComplet.GetMesh().CreateDimGroup( grps, SMESH.NODE, 'FACE2' )
+
+  logging.info("export maillage fini")
+  maillageComplet.ExportMED( fichierMaillageFissure, 0, SMESH.MED_V2_2, 1 )
+  putName(maillageComplet, nomFicFissure)
+  logging.info("fichier maillage fissure %s", fichierMaillageFissure)
+
+  if salome.sg.hasDesktop():
+    salome.sg.updateObjBrowser(1)
+
+  logging.info("maillage fissure fini")
+  
+  return maillageComplet