3 This represents a python class definition which contains
4 all necessary information about the macro object being created
8 def __init__( self, ObjectType, GeoParameters, MeshParameters, **args ):
10 Initializes the macro object to be created, saves parameters inside of it, checks for neighboring objects,
11 determines meshing parameters if necessary and finally launches the generation process.
13 import Config,GenFunctions
14 if Config.debug : print "Initializing object No. " + str(len(Config.ListObj)+1)
16 if 'publish' in args :
17 if args['publish']==0 : Config.publish = 0
18 else : Config.publish = 1
19 else : Config.publish = 1
22 self.GroupNames = args['groups']
23 for group in args['groups'] :
24 if not(group in Config.Groups) and group : Config.Groups.append(group)
25 else : self.GroupNames = [None, None, None, None]
27 if ObjectType == 'NonOrtho':
28 if not(len(GeoParameters)==4): print "Error: trying to construct a non-ortho object but the 4 constitutive vertices are not given!"
30 Xmin = min([GeoParameters[i][0] for i in range(4)])
31 Xmax = max([GeoParameters[i][0] for i in range(4)])
32 Ymin = min([GeoParameters[i][1] for i in range(4)])
33 Ymax = max([GeoParameters[i][1] for i in range(4)])
34 self.GeoPar = [(0.5*(Xmin+Xmax),0.5*(Ymin+Ymax)),(Xmax-Xmin,Ymax-Ymin)]
35 self.PtCoor = GenFunctions.SortPoints(GeoParameters)
37 self.GeoPar = GeoParameters
38 [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] ]
39 self.PtCoor = [(Xmin,Ymin),(Xmax,Ymin),(Xmax,Ymax),(Xmin,Ymax)]
41 self.Type = ObjectType
42 self.LowBound = [ self.GeoPar[0][0]-0.5*self.GeoPar[1][0], self.GeoPar[0][1]-0.5*self.GeoPar[1][1] ]
43 self.UpperBound = [ self.GeoPar[0][0]+0.5*self.GeoPar[1][0], self.GeoPar[0][1]+0.5*self.GeoPar[1][1] ]
44 self.MeshPar = MeshParameters
46 self.GeoChildrenNames = []
49 self.CheckInterfaces()
50 if 'auto' in MeshParameters : self.AutoParam()
51 if not(self.MeshPar[0]<0): self.Generate()
53 Config.ListObj.append(self)
54 print("Aborting object creation\n ")
58 This method generates the geometrical object with the corresponding mesh once all verifications (CheckInterfaces and AutoParam)
59 have been accomplished
61 import GenFunctions, Alarms, Config
62 self = {'Box11' : lambda : GenFunctions.Box11(self),
63 'Box42' : lambda : GenFunctions.Box42(self),
64 'BoxAng32' : lambda : GenFunctions.BoxAng32(self),
65 'CompBox' : lambda : GenFunctions.CompBox(self),
66 'CompBoxF' : lambda : GenFunctions.CompBoxF(self),
67 'NonOrtho' : lambda : GenFunctions.NonOrtho(self),
68 'QuartCyl' : lambda : GenFunctions.QuartCyl(self) }[self.Type]()
70 if Config.debug : Alarms.Message(self.status) # notification on the result of the generation algorithm
73 def CheckInterfaces(self):
75 This method searches for neighbours for the object being created and saves them inside the Config.Connections
76 array. This array contains 4 entries per object corresponding to West, East, South, and North neighbours.
77 Note that an object may have more than one neighbour for a given direction.
80 from GenFunctions import AddIfDifferent
81 from CompositeBox import FindCommonSide
83 Config.Connections.append([(-1,),(-1,),(-1,),(-1,)])
84 itemID = len(Config.ListObj)
85 # In all cases except non ortho, PrincipleBoxes is unitary and contains the box in question
86 # In the non-ortho case it contains all possible combinations of boxes with 3 vertices
87 PrincipleBoxes = self.PrincipleBoxes()
88 for i, TestObj in enumerate(Config.ListObj):
89 SecondaryBoxes = TestObj.PrincipleBoxes()
92 for Box0 in PrincipleBoxes:
93 for Box1 in SecondaryBoxes:
95 CenterDis = abs(Box1[0][0]-Box0[0][0])
96 Extension = 0.5*(Box1[1][0]+Box0[1][0])
97 if CenterDis - Extension < -1e-7 :
99 elif CenterDis - Extension < 1e-7 :
100 if not(FindCommonSide(self.DirBoundaries(2),TestObj.DirBoundaries(3))==[0,0]) and Box1[0][0] < Box0[0][0] : ConnX = 1
101 elif not(FindCommonSide(self.DirBoundaries(3),TestObj.DirBoundaries(2))==[0,0]) and Box1[0][0] >= Box0[0][0]: ConnX = 2
105 CenterDis = abs(Box1[0][1]-Box0[0][1])
106 Extension = 0.5*(Box1[1][1]+Box0[1][1])
107 if CenterDis - Extension < -1e-7 :
109 elif CenterDis - Extension < 1e-7 :
110 if not(FindCommonSide(self.DirBoundaries(0),TestObj.DirBoundaries(1))==[0,0]) and Box1[0][1] < Box0[0][1] : ConnY = 1
111 elif not(FindCommonSide(self.DirBoundaries(1),TestObj.DirBoundaries(0))==[0,0]) and Box1[0][1] >= Box0[0][1]: ConnY = 2
114 if not (ConnX*ConnY == 0) :
115 if max(ConnX,ConnY) == -1 and not('NonOrtho' in [self.Type,TestObj.Type]) : Alarms.Message(3)
117 if ConnX == 1 and ConnY == -1:
118 if Config.Connections[i][1] == (-1,) : Config.Connections[i][1] = (itemID,)
119 else : Config.Connections[i][1] = AddIfDifferent(Config.Connections[i][1],itemID)
120 if Config.Connections[itemID][0] == (-1,) : Config.Connections[itemID][0] = (i,)
121 else : Config.Connections[itemID][0] = AddIfDifferent(Config.Connections[itemID][0],i)
122 elif ConnX == 2 and ConnY == -1:
123 if Config.Connections[i][0] == (-1,) : Config.Connections[i][0] = (itemID,)
124 else : Config.Connections[i][0] = AddIfDifferent(Config.Connections[i][0],itemID)
125 if Config.Connections[itemID][1] == (-1,) : Config.Connections[itemID][1] = (i,)
126 else : Config.Connections[itemID][1] = AddIfDifferent(Config.Connections[itemID][1],i)
127 elif ConnY == 1 and ConnX == -1:
128 if Config.Connections[i][3] == (-1,) : Config.Connections[i][3] = (itemID,)
129 else : Config.Connections[i][3] = AddIfDifferent(Config.Connections[i][3],itemID)
130 if Config.Connections[itemID][2] == (-1,) : Config.Connections[itemID][2] = (i,)
131 else : Config.Connections[itemID][2] = AddIfDifferent(Config.Connections[itemID][2],i)
132 elif ConnY ==2 and ConnX == -1:
133 if Config.Connections[i][2] == (-1,) : Config.Connections[i][2] = (itemID,)
134 else : Config.Connections[i][2] = AddIfDifferent(Config.Connections[i][2],itemID)
135 if Config.Connections[itemID][3] == (-1,) : Config.Connections[itemID][3] = (i,)
136 else : Config.Connections[itemID][3] = AddIfDifferent(Config.Connections[itemID][3],i)
138 def AutoParam (self):
140 This method is called only if the 'auto' keyword is used inside the meshing algorithm. It is based on the
141 connection results per object and tries to find the correct parameters for obtaining a final compatible mesh
142 between the objects already present and the one being created. If this is not possible, the method gives an error
145 import Alarms, Config, GenFunctions, CompositeBox
146 MeshPar = [0,0,0,0] # initialize the mesh parameter value to be used to -1
147 [(X0,Y0),(DX,DY)] = self.GeoPar
149 for i, Conn in enumerate(Config.Connections[-1]):
150 if not ( Conn == (-1,) ): # Meaning that there is one or more neighbors on this direction
152 ToLook0 = [2,3,0,1][i]
153 ToLook1 = [3,2,1,0][i]
154 CommonSide = CompositeBox.FindCommonSide(Config.ListObj[ObjID].DirBoundaries(ToLook1),self.DirBoundaries(ToLook0))
155 #print "Common Side is:", CommonSide
156 ToLook2 = [1,0,3,2][i]
157 #print "Full Side is:", CompositeBox.IntLen(Config.ListObj[ObjID].DirBoundaries(ToLook1))
158 #print "Full Segments on this direction are:", Config.ListObj[ObjID].DirectionalMeshParams[ToLook2]
159 RealSegments = round(Config.ListObj[ObjID].DirectionalMeshParams[ToLook2]*CompositeBox.IntLen(CommonSide)/CompositeBox.IntLen(Config.ListObj[ObjID].DirBoundaries(ToLook1)))
160 #print "RealSegments :", RealSegments
162 MeshPar[i] = MeshPar[i] + RealSegments
163 ObjectsInvolved.append(ObjID+1)
164 self.DirectionalMeshParams = MeshPar
165 self.MeshPar[0] = GenFunctions.CompatibilityTest(self)
167 if self.MeshPar[0] < 0 :
169 if self.MeshPar[0] == -1 : print ("Problem encountered with object(s) no. "+str(ObjectsInvolved))
170 elif self.MeshPar[0] == -2 : print ("This object has no neighbours !!!")
172 def Boundaries (self):
174 This method returns the global boundaries of the MacObject. [Xmin,Xmax,Ymin,Ymax]
176 Xmin = min([self.DirBoundaries(i)[0] for i in [0,1]])
177 Xmax = max([self.DirBoundaries(i)[1] for i in [0,1]])
178 Ymin = min([self.DirBoundaries(i)[0] for i in [2,3]])
179 Ymax = max([self.DirBoundaries(i)[1] for i in [2,3]])
181 return [Xmin,Xmax,Ymin,Ymax]
183 def DirBoundaries (self, Direction):
185 This method returns a single interval giving [Xmin,Xmax] or [Ymin,Ymax] according to the required direction.
186 This works particularly well for nonorthogonal objects.
187 Direction : [0,1,2,3] <=> [South, North, West, East]
190 PtCoor.append(self.PtCoor[0])
191 if type(Direction) is str :
192 Dir = { 'South' : lambda : 0,
193 'North' : lambda : 1,
195 'East' : lambda : 3,}[Direction]()
196 else : Dir = int(Direction)
198 PtIndex = [0,2,3,1][Dir]
199 DirIndex = [0,0,1,1][Dir]
201 return sorted([PtCoor[PtIndex][DirIndex],PtCoor[PtIndex+1][DirIndex]])
202 def DirVectors (self, Direction):
204 This method returns for a given object, the real vectors which define a given direction
205 The interest in using this method is for non-orthogonal objects where the sides can be
206 deviated from the orthogonal basis vectors
208 if type(Direction) is str :
209 Dir = { 'South' : lambda : 0,
210 'North' : lambda : 1,
212 'East' : lambda : 3,}[Direction]()
213 else : Dir = int(Direction)
215 PtCoor.append(self.PtCoor[0])
216 PtIndex = [0,2,3,1][Dir]
217 return [PtCoor[PtIndex+1][0]-PtCoor[PtIndex][0],PtCoor[PtIndex+1][1]-PtCoor[PtIndex][1],0.]
219 def GetBorder (self, Criterion):
220 import geompy, GenFunctions
222 if type(Criterion) is str :
223 Crit = {'South' : lambda : 0,
224 'North' : lambda : 1,
226 'East' : lambda : 3,}[Criterion]()
227 else : Crit = int(Criterion)
231 Boundaries = self.Boundaries()
232 Research = {0 : lambda : [self.DirVectors(0),1,Boundaries[2]],
233 1 : lambda : [self.DirVectors(1),1,Boundaries[3]],
234 2 : lambda : [self.DirVectors(2),0,Boundaries[0]],
235 3 : lambda : [self.DirVectors(3),0,Boundaries[1]], }[Crit]()
237 for i,ElemObj in enumerate(self.GeoChildren):
238 EdgeIDs = geompy.ExtractShapes(ElemObj,6)# List of Edge IDs belonging to ElemObj
240 if GenFunctions.IsParallel(Edge,Research[0]):
241 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 :
242 AcceptedObj.append(Edge)
244 CenterSrchPar = {'NE' : lambda : [-1., -1.],
245 'NW' : lambda : [ 1., -1.],
246 'SW' : lambda : [ 1., 1.],
247 'SE' : lambda : [-1., 1.], }[self.MeshPar[1]]()
248 Radius = self.GeoPar[1][1]*float(self.MeshPar[2])/(self.MeshPar[2]+1)
249 Center = (self.GeoPar[0][0]+CenterSrchPar[0]*self.GeoPar[1][0]/2.,self.GeoPar[0][1]+CenterSrchPar[1]*self.GeoPar[1][1]/2.,0.)
250 for i,ElemObj in enumerate(self.GeoChildren):
251 EdgeIDs = geompy.ExtractShapes(ElemObj,6)# List of Edge IDs belonging to ElemObj
253 if GenFunctions.IsOnCircle(Edge,Center,Radius):
254 AcceptedObj.append(Edge)
257 def PrincipleBoxes (self):
259 This function returns all possible combination rectangular shape objects that can contain at least 3 of the principle vertices
260 constituting the MacObject. This is indispensible for the Non-ortho types and shall return a number of 24 possible combinations
262 from itertools import combinations
264 if self.Type == 'NonOrtho':
265 for combi in combinations(range(4),3):
266 Xmin = min([self.PtCoor[i][0] for i in combi])
267 Xmax = max([self.PtCoor[i][0] for i in combi])
268 Ymin = min([self.PtCoor[i][1] for i in combi])
269 Ymax = max([self.PtCoor[i][1] for i in combi])
270 Boxes.append([(0.5*(Xmin+Xmax),0.5*(Ymin+Ymax)),(Xmax-Xmin,Ymax-Ymin)])
272 Boxes = [self.GeoPar]