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