1 # Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 # Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
26 This represents a python class definition which contains
27 all necessary information about the macro object being created
31 def __init__( self, ObjectType, GeoParameters, MeshParameters, **args ):
33 Initializes the macro object to be created, saves parameters inside of it, checks for neighboring objects,
34 determines meshing parameters if necessary and finally launches the generation process.
36 import Config,GenFunctions
37 if Config.debug : print "Initializing object No. " + str(len(Config.ListObj)+1)
39 if 'publish' in args :
40 if args['publish']==0 : Config.publish = 0
41 else : Config.publish = 1
42 else : Config.publish = 1
45 self.GroupNames = args['groups']
46 for group in args['groups'] :
47 if not(group in Config.Groups) and group : Config.Groups.append(group)
48 else : self.GroupNames = [None, None, None, None]
50 if ObjectType == 'NonOrtho':
51 if not(len(GeoParameters)==4): print "Error: trying to construct a non-ortho object but the 4 constitutive vertices are not given!"
53 Xmin = min([GeoParameters[i][0] for i in range(4)])
54 Xmax = max([GeoParameters[i][0] for i in range(4)])
55 Ymin = min([GeoParameters[i][1] for i in range(4)])
56 Ymax = max([GeoParameters[i][1] for i in range(4)])
57 self.GeoPar = [(0.5*(Xmin+Xmax),0.5*(Ymin+Ymax)),(Xmax-Xmin,Ymax-Ymin)]
58 self.PtCoor = GenFunctions.SortPoints(GeoParameters)
60 self.GeoPar = GeoParameters
61 [Xmin,Ymin,Xmax,Ymax] = [ self.GeoPar[0][0]-0.5*self.GeoPar[1][0], self.GeoPar[0][1]-0.5*self.GeoPar[1][1] ] + [ self.GeoPar[0][0]+0.5*self.GeoPar[1][0], self.GeoPar[0][1]+0.5*self.GeoPar[1][1] ]
62 self.PtCoor = [(Xmin,Ymin),(Xmax,Ymin),(Xmax,Ymax),(Xmin,Ymax)]
64 self.Type = ObjectType
65 self.LowBound = [ self.GeoPar[0][0]-0.5*self.GeoPar[1][0], self.GeoPar[0][1]-0.5*self.GeoPar[1][1] ]
66 self.UpperBound = [ self.GeoPar[0][0]+0.5*self.GeoPar[1][0], self.GeoPar[0][1]+0.5*self.GeoPar[1][1] ]
67 self.MeshPar = MeshParameters
69 self.GeoChildrenNames = []
72 self.CheckInterfaces()
73 if 'auto' in MeshParameters : self.AutoParam()
74 if not(self.MeshPar[0]<0): self.Generate()
76 Config.ListObj.append(self)
77 print("Aborting object creation\n ")
81 This method generates the geometrical object with the corresponding mesh once all verifications (CheckInterfaces and AutoParam)
82 have been accomplished
84 import GenFunctions, Alarms, Config
85 self = {'Box11' : lambda : GenFunctions.Box11(self),
86 'Box42' : lambda : GenFunctions.Box42(self),
87 'BoxAng32' : lambda : GenFunctions.BoxAng32(self),
88 'CompBox' : lambda : GenFunctions.CompBox(self),
89 'CompBoxF' : lambda : GenFunctions.CompBoxF(self),
90 'NonOrtho' : lambda : GenFunctions.NonOrtho(self),
91 'QuartCyl' : lambda : GenFunctions.QuartCyl(self) }[self.Type]()
93 if Config.debug : Alarms.Message(self.status) # notification on the result of the generation algorithm
96 def CheckInterfaces(self):
98 This method searches for neighbours for the object being created and saves them inside the Config.Connections
99 array. This array contains 4 entries per object corresponding to West, East, South, and North neighbours.
100 Note that an object may have more than one neighbour for a given direction.
102 import Alarms, Config
103 from GenFunctions import AddIfDifferent
104 from CompositeBox import FindCommonSide
106 Config.Connections.append([(-1,),(-1,),(-1,),(-1,)])
107 itemID = len(Config.ListObj)
108 # In all cases except non ortho, PrincipleBoxes is unitary and contains the box in question
109 # In the non-ortho case it contains all possible combinations of boxes with 3 vertices
110 PrincipleBoxes = self.PrincipleBoxes()
111 for i, TestObj in enumerate(Config.ListObj):
112 SecondaryBoxes = TestObj.PrincipleBoxes()
115 for Box0 in PrincipleBoxes:
116 for Box1 in SecondaryBoxes:
118 CenterDis = abs(Box1[0][0]-Box0[0][0])
119 Extension = 0.5*(Box1[1][0]+Box0[1][0])
120 if CenterDis - Extension < -1e-7 :
122 elif CenterDis - Extension < 1e-7 :
123 if not(FindCommonSide(self.DirBoundaries(2),TestObj.DirBoundaries(3))==[0,0]) and Box1[0][0] < Box0[0][0] : ConnX = 1
124 elif not(FindCommonSide(self.DirBoundaries(3),TestObj.DirBoundaries(2))==[0,0]) and Box1[0][0] >= Box0[0][0]: ConnX = 2
128 CenterDis = abs(Box1[0][1]-Box0[0][1])
129 Extension = 0.5*(Box1[1][1]+Box0[1][1])
130 if CenterDis - Extension < -1e-7 :
132 elif CenterDis - Extension < 1e-7 :
133 if not(FindCommonSide(self.DirBoundaries(0),TestObj.DirBoundaries(1))==[0,0]) and Box1[0][1] < Box0[0][1] : ConnY = 1
134 elif not(FindCommonSide(self.DirBoundaries(1),TestObj.DirBoundaries(0))==[0,0]) and Box1[0][1] >= Box0[0][1]: ConnY = 2
137 if not (ConnX*ConnY == 0) :
138 if max(ConnX,ConnY) == -1 and not('NonOrtho' in [self.Type,TestObj.Type]) : Alarms.Message(3)
140 if ConnX == 1 and ConnY == -1:
141 if Config.Connections[i][1] == (-1,) : Config.Connections[i][1] = (itemID,)
142 else : Config.Connections[i][1] = AddIfDifferent(Config.Connections[i][1],itemID)
143 if Config.Connections[itemID][0] == (-1,) : Config.Connections[itemID][0] = (i,)
144 else : Config.Connections[itemID][0] = AddIfDifferent(Config.Connections[itemID][0],i)
145 elif ConnX == 2 and ConnY == -1:
146 if Config.Connections[i][0] == (-1,) : Config.Connections[i][0] = (itemID,)
147 else : Config.Connections[i][0] = AddIfDifferent(Config.Connections[i][0],itemID)
148 if Config.Connections[itemID][1] == (-1,) : Config.Connections[itemID][1] = (i,)
149 else : Config.Connections[itemID][1] = AddIfDifferent(Config.Connections[itemID][1],i)
150 elif ConnY == 1 and ConnX == -1:
151 if Config.Connections[i][3] == (-1,) : Config.Connections[i][3] = (itemID,)
152 else : Config.Connections[i][3] = AddIfDifferent(Config.Connections[i][3],itemID)
153 if Config.Connections[itemID][2] == (-1,) : Config.Connections[itemID][2] = (i,)
154 else : Config.Connections[itemID][2] = AddIfDifferent(Config.Connections[itemID][2],i)
155 elif ConnY ==2 and ConnX == -1:
156 if Config.Connections[i][2] == (-1,) : Config.Connections[i][2] = (itemID,)
157 else : Config.Connections[i][2] = AddIfDifferent(Config.Connections[i][2],itemID)
158 if Config.Connections[itemID][3] == (-1,) : Config.Connections[itemID][3] = (i,)
159 else : Config.Connections[itemID][3] = AddIfDifferent(Config.Connections[itemID][3],i)
161 def AutoParam (self):
163 This method is called only if the 'auto' keyword is used inside the meshing algorithm. It is based on the
164 connection results per object and tries to find the correct parameters for obtaining a final compatible mesh
165 between the objects already present and the one being created. If this is not possible, the method gives an error
168 import Alarms, Config, GenFunctions, CompositeBox
169 MeshPar = [0,0,0,0] # initialize the mesh parameter value to be used to -1
170 [(X0,Y0),(DX,DY)] = self.GeoPar
172 for i, Conn in enumerate(Config.Connections[-1]):
173 if not ( Conn == (-1,) ): # Meaning that there is one or more neighbors on this direction
175 ToLook0 = [2,3,0,1][i]
176 ToLook1 = [3,2,1,0][i]
177 CommonSide = CompositeBox.FindCommonSide(Config.ListObj[ObjID].DirBoundaries(ToLook1),self.DirBoundaries(ToLook0))
178 #print "Common Side is:", CommonSide
179 ToLook2 = [1,0,3,2][i]
180 #print "Full Side is:", CompositeBox.IntLen(Config.ListObj[ObjID].DirBoundaries(ToLook1))
181 #print "Full Segments on this direction are:", Config.ListObj[ObjID].DirectionalMeshParams[ToLook2]
182 RealSegments = round(Config.ListObj[ObjID].DirectionalMeshParams[ToLook2]*CompositeBox.IntLen(CommonSide)/CompositeBox.IntLen(Config.ListObj[ObjID].DirBoundaries(ToLook1)))
183 #print "RealSegments :", RealSegments
185 MeshPar[i] = MeshPar[i] + RealSegments
186 ObjectsInvolved.append(ObjID+1)
187 self.DirectionalMeshParams = MeshPar
188 self.MeshPar[0] = GenFunctions.CompatibilityTest(self)
190 if self.MeshPar[0] < 0 :
192 if self.MeshPar[0] == -1 : print ("Problem encountered with object(s) no. "+str(ObjectsInvolved))
193 elif self.MeshPar[0] == -2 : print ("This object has no neighbours !!!")
195 def Boundaries (self):
197 This method returns the global boundaries of the MacObject. [Xmin,Xmax,Ymin,Ymax]
199 Xmin = min([self.DirBoundaries(i)[0] for i in [0,1]])
200 Xmax = max([self.DirBoundaries(i)[1] for i in [0,1]])
201 Ymin = min([self.DirBoundaries(i)[0] for i in [2,3]])
202 Ymax = max([self.DirBoundaries(i)[1] for i in [2,3]])
204 return [Xmin,Xmax,Ymin,Ymax]
206 def DirBoundaries (self, Direction):
208 This method returns a single interval giving [Xmin,Xmax] or [Ymin,Ymax] according to the required direction.
209 This works particularly well for nonorthogonal objects.
210 Direction : [0,1,2,3] <=> [South, North, West, East]
213 PtCoor.append(self.PtCoor[0])
214 if type(Direction) is str :
215 Dir = { 'South' : lambda : 0,
216 'North' : lambda : 1,
218 'East' : lambda : 3,}[Direction]()
219 else : Dir = int(Direction)
221 PtIndex = [0,2,3,1][Dir]
222 DirIndex = [0,0,1,1][Dir]
224 return sorted([PtCoor[PtIndex][DirIndex],PtCoor[PtIndex+1][DirIndex]])
225 def DirVectors (self, Direction):
227 This method returns for a given object, the real vectors which define a given direction
228 The interest in using this method is for non-orthogonal objects where the sides can be
229 deviated from the orthogonal basis vectors
231 if type(Direction) is str :
232 Dir = { 'South' : lambda : 0,
233 'North' : lambda : 1,
235 'East' : lambda : 3,}[Direction]()
236 else : Dir = int(Direction)
238 PtCoor.append(self.PtCoor[0])
239 PtIndex = [0,2,3,1][Dir]
240 return [PtCoor[PtIndex+1][0]-PtCoor[PtIndex][0],PtCoor[PtIndex+1][1]-PtCoor[PtIndex][1],0.]
242 def GetBorder (self, Criterion):
243 import GenFunctions, Config
245 from salome.geom import geomBuilder
246 geompy = geomBuilder.New( Config.theStudy )
248 if type(Criterion) is str :
249 Crit = {'South' : lambda : 0,
250 'North' : lambda : 1,
252 'East' : lambda : 3,}[Criterion]()
253 else : Crit = int(Criterion)
257 Boundaries = self.Boundaries()
258 Research = {0 : lambda : [self.DirVectors(0),1,Boundaries[2]],
259 1 : lambda : [self.DirVectors(1),1,Boundaries[3]],
260 2 : lambda : [self.DirVectors(2),0,Boundaries[0]],
261 3 : lambda : [self.DirVectors(3),0,Boundaries[1]], }[Crit]()
263 for i,ElemObj in enumerate(self.GeoChildren):
264 EdgeIDs = geompy.ExtractShapes(ElemObj,6)# List of Edge IDs belonging to ElemObj
266 if GenFunctions.IsParallel(Edge,Research[0]):
267 if abs( geompy.PointCoordinates(geompy.GetVertexByIndex(Edge,0))[Research[1]] - Research[2] )< 1e-6 or abs( geompy.PointCoordinates(geompy.GetVertexByIndex(Edge,1))[Research[1]] - Research[2] )< 1e-6 :
268 AcceptedObj.append(Edge)
270 CenterSrchPar = {'NE' : lambda : [-1., -1.],
271 'NW' : lambda : [ 1., -1.],
272 'SW' : lambda : [ 1., 1.],
273 'SE' : lambda : [-1., 1.], }[self.MeshPar[1]]()
274 Radius = self.GeoPar[1][1]*float(self.MeshPar[2])/(self.MeshPar[2]+1)
275 Center = (self.GeoPar[0][0]+CenterSrchPar[0]*self.GeoPar[1][0]/2.,self.GeoPar[0][1]+CenterSrchPar[1]*self.GeoPar[1][1]/2.,0.)
276 for i,ElemObj in enumerate(self.GeoChildren):
277 EdgeIDs = geompy.ExtractShapes(ElemObj,6)# List of Edge IDs belonging to ElemObj
279 if GenFunctions.IsOnCircle(Edge,Center,Radius):
280 AcceptedObj.append(Edge)
283 def PrincipleBoxes (self):
285 This function returns all possible combination rectangular shape objects that can contain at least 3 of the principle vertices
286 constituting the MacObject. This is indispensible for the Non-ortho types and shall return a number of 24 possible combinations
288 from itertools import combinations
290 if self.Type == 'NonOrtho':
291 for combi in combinations(range(4),3):
292 Xmin = min([self.PtCoor[i][0] for i in combi])
293 Xmax = max([self.PtCoor[i][0] for i in combi])
294 Ymin = min([self.PtCoor[i][1] for i in combi])
295 Ymax = max([self.PtCoor[i][1] for i in combi])
296 Boxes.append([(0.5*(Xmin+Xmax),0.5*(Ymin+Ymax)),(Xmax-Xmin,Ymax-Ymin)])
298 Boxes = [self.GeoPar]