Salome HOME
simplification
[modules/smesh.git] / src / Tools / blocFissure / gmu / listOfExtraFunctions.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2014-2021  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 """Cette fonction permet de scanner la liste de noeuds qui composent le maillage passé en paramètre
21
22 Created on Mon Jun 23 14:49:36 2014
23 @author: I48174 (Olivier HOAREAU)
24 """
25
26 import logging
27 import SMESH
28 from .geomsmesh import smesh
29
30 def lookForCorner(maillageAScanner):
31
32   """ Cette fonction permet de scanner la liste de noeuds qui composent le
33       maillage passé en paramètre. On recherche un ou plusieurs coins, ce
34       qui implique les caractéristiques suivantes:
35           - le noeud doit appartenir au moins à trois éléments distincts
36           - chaque élément doit appartenir à un ensemble distinct
37       La fonction renvoie une liste de coins par l'intermédiaire de l'IDs
38       chaque noeud. La liste contient en général au maximum deux coins.
39   """
40
41   logging.info("start")
42
43   allNodeIds = maillageAScanner.GetNodesId()  # On stocke tout les noeuds
44   listOfCorners = list()
45   for noeud in allNodeIds:
46     # On parcours la liste de noeuds
47     listOfElements = maillageAScanner.GetNodeInverseElements(noeud)
48     if len(listOfElements) >=3:
49       # On teste le nombre d'éléments qui partagent le même noeud
50       # --- Filtre selon le critère 'coplanar' --- #
51       listOfCriterion = [smesh.GetCriterion(SMESH.FACE, SMESH.FT_CoplanarFaces, \
52                           SMESH.FT_Undefined, elem, SMESH.FT_Undefined, SMESH.FT_Undefined, 30) \
53                           for elem in listOfElements]
54       listOfFilters = [smesh.GetFilterFromCriteria([criteria]) for criteria in listOfCriterion]
55       listOfSets = [maillageAScanner.GetIdsFromFilter(filtre) for filtre in listOfFilters]
56       if listOfSets.count(listOfSets[0]) == len(listOfSets):
57         # Si toutes les listes d'éléments sont similaires, on retourne
58         # au début pour éviter de travailler sur des éléments inutiles.
59         # Exemple : un noeud appartenant à 4 éléments sur la même face.
60         continue
61       for l_aux in listOfSets:
62         while listOfSets.count(l_aux) > 1:
63             # On supprime tant que la liste d'éléments n'est pas unique.
64           listOfSets.remove(l_aux)
65       if len(listOfSets) >= 3:
66         # Si on a au moins 3 listes d'élements différentes, on considère
67         # qu'il y a présence d'un coin.
68         listOfCorners.append(noeud)
69
70   return listOfCorners
71
72 def createLinesFromMesh(maillageSupport):
73
74   """ Cette fonction permet de générer une liste de lignes à partir du
75       maillage support passé en paramètre. On démarre à partir d'un coin
76       simple et on parcourt tout les noeuds pour former une ligne. Soit la
77       figure ci-dessous :
78
79           1_____4_____7    On part du coin N1, et on cherche les noeuds
80           |     |     |    successifs tels que [1, 2, 3]. Lorsqu'on arrive
81           |  1  |  3  |    arrive sur le noeud de fin de ligne N3, on repart
82           |     |     |    du noeud précédent du premier élément (E1), à
83           2_____5_____8    savoir le noeud N4. On suit les noeuds succesifs
84           |     |     |    [4, 5, 6] comme précédemment et ainsi de suite.
85           |  2  |  4  |    Lorsqu'on arrive sur le dernier noeud de la
86           |     |     |    dernière ligne, à savoir le noeud N9, on considère
87           3_____6_____9    que toutes les lignes sont créées.
88
89       La fonction retourne une liste de lignes utilisées par la suite.
90   """
91
92   logging.info("start")
93
94   allNodeIds = maillageSupport.GetNodesId()
95   while len(allNodeIds):
96     nodeIds = allNodeIds
97     for idNode in nodeIds: # rechercher un coin
98       elems = maillageSupport.GetNodeInverseElements(idNode)
99       if len(elems) == 1:
100         # un coin: un noeud, un element quadrangle
101         elem = elems[0]
102         idNode_c = idNode
103         break
104     idStart = idNode_c # le noeud de coin
105     elemStart = elem # l'élément quadrangle au coin
106     xyz = maillageSupport.GetNodeXYZ(idStart)
107     logging.debug("idStart %s, coords %s", idStart, str(xyz))
108
109     nodelines = list() # on va constituer une liste de lignes de points
110     nextLine = True
111     ligneFinale = False
112     while nextLine:
113       logging.debug("--- une ligne")
114       idNode = idStart
115       elem = elemStart
116       if ligneFinale:
117         agauche = False  # sens de parcours des 4 noeuds d'un quadrangle
118         nextLine = False
119       else:
120         agauche = True
121       ligneIncomplete = True  # on commence une ligne de points
122       debutLigne = True
123       nodeline = list()
124       elemline = list()
125       while ligneIncomplete:  # compléter la ligne de points
126         nodeline.append(idNode)
127         allNodeIds.remove(idNode)
128         elemline.append(elem)
129         nodes = maillageSupport.GetElemNodes(elem)
130         i_aux = nodes.index(idNode)  # repérer l'index du noeud courant (i_aux) dans l'élément quadrangle (0 a 3)
131         if agauche:              # déterminer le noeud suivant (j_aux) et celui opposé (k_aux) dans le quadrangle
132           if i_aux < 3:
133             j_aux = i_aux+1
134           else:
135             j_aux = 0
136           if j_aux < 3:
137             k_aux = j_aux+1
138           else:
139             k_aux = 0
140         else:
141           if i_aux > 0:
142             j_aux = i_aux -1
143           else:
144             j_aux = 3
145           if j_aux > 0:
146             k_aux = j_aux -1
147           else:
148             k_aux = 3
149         isuiv = nodes[j_aux]   # noeud suivant
150         iapres = nodes[k_aux]  # noeud opposé
151         if debutLigne:
152           debutLigne = False
153           # précédent a trouver, dernière ligne : précédent au lieu de suivant
154           if agauche:
155             if i_aux > 0:
156               iprec = nodes[i_aux -1]
157             else:
158               iprec = nodes[3]
159             idStart = iprec
160             elems3 = maillageSupport.GetNodeInverseElements(iprec)
161             if len(elems3) == 1: # autre coin
162               ligneFinale = True
163             else:
164               for elem3 in elems3:
165                 if elem3 != elem:
166                   elemStart = elem3
167                   break
168
169         #print nodes, idNode, isuiv, iapres
170         elems1 = maillageSupport.GetNodeInverseElements(isuiv)
171         elems2 = maillageSupport.GetNodeInverseElements(iapres)
172         ligneIncomplete = False
173         for elem2 in elems2:
174           if elems1.count(elem2) and elem2 != elem:
175             ligneIncomplete = True
176             idNode = isuiv
177             elem = elem2
178             break
179         if not  ligneIncomplete:
180           nodeline.append(isuiv)
181           allNodeIds.remove(isuiv)
182       logging.debug("nodeline %s", nodeline)
183       logging.debug("elemline %s", elemline)
184       nodelines.append(nodeline)
185
186     # on a constitué une liste de lignes de points connexes
187     logging.debug("dimensions [%s, %s]", len(nodelines),  len(nodeline))
188
189   return nodelines
190
191 def createNewMeshesFromCorner(maillageSupport, listOfCorners):
192
193   """ Cette fonction permet de générer un nouveau maillage plus facile à
194       utiliser. On démarre d'un coin et on récupère les trois éléments
195       auquel le noeud appartient. Grâce à un filtre 'coplanar' sur les trois
196       éléments, on peut générer des faces distinctes.
197   """
198
199   logging.info("start")
200
201   tmp = list()
202   listOfNewMeshes = list()
203   for corner in listOfCorners:
204     elems = maillageSupport.GetNodeInverseElements(corner)
205     for i_aux, elem in enumerate(elems):
206       # --- Filtre selon le critère 'coplanar' --- #
207       critere = smesh.GetCriterion(SMESH.FACE, SMESH.FT_CoplanarFaces, \
208                                     SMESH.FT_Undefined, elem, SMESH.FT_Undefined, SMESH.FT_Undefined, 30)
209       filtre = smesh.GetFilterFromCriteria([critere])
210       grp = maillageSupport.GroupOnFilter(SMESH.FACE, 'grp', filtre)
211       # On copie le maillage en fonction du filtre
212       msh = smesh.CopyMesh(grp, 'new_{0}'.format(i_aux+1), False, True)
213       # On stocke l'ensemble des noeuds du maillage dans tmp
214       # On ajoute le maillage à la liste des nouveaux maillages
215       # seulement s'il n'y est pas déjà
216       tmp.append(msh.GetNodesId())
217       if ( tmp.count(msh.GetNodesId()) <= 1 ):
218         listOfNewMeshes.append(msh)
219
220   return listOfNewMeshes