midas-civil 1.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- midas_civil/_BoundaryChangeAssignment.py +278 -0
- midas_civil/__init__.py +51 -0
- midas_civil/_analysiscontrol.py +585 -0
- midas_civil/_boundary.py +888 -0
- midas_civil/_construction.py +1004 -0
- midas_civil/_element.py +1346 -0
- midas_civil/_group.py +337 -0
- midas_civil/_load.py +967 -0
- midas_civil/_loadcomb.py +159 -0
- midas_civil/_mapi.py +249 -0
- midas_civil/_material.py +1692 -0
- midas_civil/_model.py +522 -0
- midas_civil/_movingload.py +1479 -0
- midas_civil/_node.py +532 -0
- midas_civil/_result_table.py +929 -0
- midas_civil/_result_test.py +5455 -0
- midas_civil/_section/_TapdbSecSS.py +175 -0
- midas_civil/_section/__init__.py +413 -0
- midas_civil/_section/_compositeSS.py +283 -0
- midas_civil/_section/_dbSecSS.py +164 -0
- midas_civil/_section/_offsetSS.py +53 -0
- midas_civil/_section/_pscSS copy.py +455 -0
- midas_civil/_section/_pscSS.py +822 -0
- midas_civil/_section/_tapPSC12CellSS.py +565 -0
- midas_civil/_section/_unSupp.py +58 -0
- midas_civil/_settlement.py +161 -0
- midas_civil/_temperature.py +677 -0
- midas_civil/_tendon.py +1016 -0
- midas_civil/_thickness.py +147 -0
- midas_civil/_utils.py +529 -0
- midas_civil/_utilsFunc/__init__.py +0 -0
- midas_civil/_utilsFunc/_line2plate.py +636 -0
- midas_civil/_view.py +891 -0
- midas_civil/_view_trial.py +430 -0
- midas_civil/_visualise.py +347 -0
- midas_civil-1.4.1.dist-info/METADATA +74 -0
- midas_civil-1.4.1.dist-info/RECORD +40 -0
- midas_civil-1.4.1.dist-info/WHEEL +5 -0
- midas_civil-1.4.1.dist-info/licenses/LICENSE +21 -0
- midas_civil-1.4.1.dist-info/top_level.txt +1 -0
midas_civil/_node.py
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
from ._mapi import MidasAPI
|
|
2
|
+
from ._utils import zz_add_to_dict,_convItem2List , sFlatten
|
|
3
|
+
from math import hypot
|
|
4
|
+
from ._group import _add_node_2_stGroup
|
|
5
|
+
from typing import Literal
|
|
6
|
+
import numpy as np
|
|
7
|
+
from ._group import Group
|
|
8
|
+
|
|
9
|
+
def dist_tol(a,b):
|
|
10
|
+
return hypot((a.X-b.X),(a.Y-b.Y),(a.Z-b.Z)) < 0.00001 #TOLERANCE BUILT IN (UNIT INDEP)
|
|
11
|
+
|
|
12
|
+
def cell(point,size=1): #SIZE OF GRID - string format
|
|
13
|
+
# return str(f"{int(point.X//size)},{int(point.Y//size)},{int(point.Z//size)}")
|
|
14
|
+
return str(f"{int(point.X)},{int(point.Y)},{int(point.Z)}")
|
|
15
|
+
|
|
16
|
+
# def _cellGrid():
|
|
17
|
+
# [float(x.strip()) for x in list(Node.Grid.keys())split(",")]
|
|
18
|
+
# -------- FUNCTIONS ARE DEFINED BELOW TO RECOGNISE NODE CLASS ----------------
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class _hNode:
|
|
22
|
+
ID,X,Y,Z,AXIS = 0,0,0,0,0
|
|
23
|
+
|
|
24
|
+
#5 Class to create nodes
|
|
25
|
+
class Node:
|
|
26
|
+
"""X ordinate, Y ordinate, Z ordinate, Node ID (optional). \nSample: Node(1,0,5)"""
|
|
27
|
+
nodes:list[_hNode] = [] # Node object stores in a list
|
|
28
|
+
ids:list[int] = [] # Node IDs used for auto increment of ID and replacement of nodes
|
|
29
|
+
Grid ={} # Node object in cube grid
|
|
30
|
+
__nodeDic__ = {} # Stores node object corresponding to ID (faster get with nodebyID)
|
|
31
|
+
def __init__(self,x:float,y:float,z:float,id:int=None,group:str='',merge:bool=True):
|
|
32
|
+
''' Create Node object
|
|
33
|
+
|
|
34
|
+
Parameters:
|
|
35
|
+
x: X - ordinate of node
|
|
36
|
+
y: Y - ordinate of node
|
|
37
|
+
z: Z - ordinate of node
|
|
38
|
+
id: Node ID (default 0 for auto-increment)
|
|
39
|
+
mat: Material property number (default 1)
|
|
40
|
+
group: Structure group of the element (str or list; 'SG1' or ['SG1','SG2'])
|
|
41
|
+
merge: If enabled, checks for existing nodes and return their IDs. No additional/duplicate node will be created.
|
|
42
|
+
|
|
43
|
+
Examples:
|
|
44
|
+
```python
|
|
45
|
+
Node(0,0,0, id =1 , group = 'Support', merge=1)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
'''
|
|
49
|
+
|
|
50
|
+
if id == None: id =0
|
|
51
|
+
#----------------- ORIGINAL -----------------------
|
|
52
|
+
|
|
53
|
+
if Node.ids == []:
|
|
54
|
+
node_count = 1
|
|
55
|
+
else:
|
|
56
|
+
node_count = max(Node.ids)+1
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
self.X = round(x,6)
|
|
60
|
+
self.Y = round(y,6)
|
|
61
|
+
self.Z = round(z,6)
|
|
62
|
+
|
|
63
|
+
if id == 0 : self.ID = node_count
|
|
64
|
+
if id != 0 : self.ID = id
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
#REPLACE - No merge check
|
|
68
|
+
if id in Node.ids:
|
|
69
|
+
|
|
70
|
+
index=Node.ids.index(id)
|
|
71
|
+
n_orig = Node.nodes[index]
|
|
72
|
+
loc_orig = str(cell(n_orig))
|
|
73
|
+
Node.Grid[loc_orig].remove(n_orig)
|
|
74
|
+
|
|
75
|
+
loc_new = str(cell(self))
|
|
76
|
+
|
|
77
|
+
zz_add_to_dict(Node.Grid,loc_new,self)
|
|
78
|
+
Node.nodes[index]=self
|
|
79
|
+
Node.__nodeDic__[str(id)] = self
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
#CREATE NEW - Merge Check based on input
|
|
83
|
+
else:
|
|
84
|
+
self.AXIS = [[0,0,0],[0,0,0],[0,0,0]]
|
|
85
|
+
cell_loc = str(cell(self))
|
|
86
|
+
|
|
87
|
+
if cell_loc in Node.Grid:
|
|
88
|
+
|
|
89
|
+
if merge :
|
|
90
|
+
chk=0 #OPTIONAL
|
|
91
|
+
for node in Node.Grid[cell_loc]:
|
|
92
|
+
if dist_tol(self,node):
|
|
93
|
+
|
|
94
|
+
chk=1
|
|
95
|
+
self.ID=node.ID
|
|
96
|
+
self.AXIS = node.AXIS
|
|
97
|
+
if chk==0:
|
|
98
|
+
|
|
99
|
+
self.AXIS = [[0,0,0],[0,0,0],[0,0,0]]
|
|
100
|
+
Node.nodes.append(self)
|
|
101
|
+
Node.ids.append(self.ID)
|
|
102
|
+
Node.Grid[cell_loc].append(self)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
else:
|
|
106
|
+
|
|
107
|
+
Node.nodes.append(self)
|
|
108
|
+
Node.ids.append(self.ID)
|
|
109
|
+
Node.Grid[cell_loc].append(self)
|
|
110
|
+
else:
|
|
111
|
+
|
|
112
|
+
Node.Grid[cell_loc]=[]
|
|
113
|
+
Node.nodes.append(self)
|
|
114
|
+
Node.ids.append(self.ID)
|
|
115
|
+
Node.Grid[cell_loc].append(self)
|
|
116
|
+
Node.__nodeDic__[str(self.ID)] = self
|
|
117
|
+
|
|
118
|
+
if group !="":
|
|
119
|
+
_add_node_2_stGroup(self.ID,group)
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def LOC(self):
|
|
123
|
+
''' Return X,Y,Z as a tuple'''
|
|
124
|
+
return (self.X,self.Y,self.Z)
|
|
125
|
+
|
|
126
|
+
def __str__(self):
|
|
127
|
+
return f"NODE ID : {self.ID} | X:{self.X} , Y:{self.Y} , Z:{self.Z} \n{self.__dict__}"
|
|
128
|
+
|
|
129
|
+
@classmethod
|
|
130
|
+
def json(cls):
|
|
131
|
+
json = {"Assign":{}}
|
|
132
|
+
for i in cls.nodes:
|
|
133
|
+
json["Assign"][i.ID]={"X":i.X,"Y":i.Y,"Z":i.Z}
|
|
134
|
+
return json
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
137
|
+
def create():
|
|
138
|
+
MidasAPI("PUT","/db/NODE",Node.json())
|
|
139
|
+
|
|
140
|
+
@staticmethod
|
|
141
|
+
def get():
|
|
142
|
+
return MidasAPI("GET","/db/NODE")
|
|
143
|
+
|
|
144
|
+
@staticmethod
|
|
145
|
+
def sync():
|
|
146
|
+
Node.clear()
|
|
147
|
+
a = Node.get()
|
|
148
|
+
if a != {'message': ''}:
|
|
149
|
+
if list(a['NODE'].keys()) != []:
|
|
150
|
+
for j in a['NODE'].keys():
|
|
151
|
+
Node(round(a['NODE'][j]['X'],6), round(a['NODE'][j]['Y'],6), round(a['NODE'][j]['Z'],6), id=int(j), group='', merge=False)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@staticmethod
|
|
155
|
+
def delete():
|
|
156
|
+
MidasAPI("DELETE","/db/NODE/")
|
|
157
|
+
Node.clear()
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def clear():
|
|
161
|
+
Node.nodes=[]
|
|
162
|
+
Node.ids=[]
|
|
163
|
+
Node.Grid={}
|
|
164
|
+
Node.__nodeDic__ = {}
|
|
165
|
+
|
|
166
|
+
@staticmethod
|
|
167
|
+
def SE(s_loc:list,e_loc:list,n:int=1,id:int=None,group:str='',merge:bool=True):
|
|
168
|
+
if isinstance(s_loc,Node):
|
|
169
|
+
s_loc = (s_loc.X,s_loc.Y,s_loc.Z)
|
|
170
|
+
if isinstance(e_loc,Node):
|
|
171
|
+
e_loc = (e_loc.X,e_loc.Y,e_loc.Z)
|
|
172
|
+
|
|
173
|
+
beam_nodes =[]
|
|
174
|
+
i_loc = np.linspace(s_loc,e_loc,n+1)
|
|
175
|
+
for i in range(n+1):
|
|
176
|
+
beam_nodes.append(Node(i_loc[i][0].item(),i_loc[i][1].item(),i_loc[i][2].item(),id,group,merge))
|
|
177
|
+
|
|
178
|
+
return beam_nodes
|
|
179
|
+
|
|
180
|
+
@staticmethod
|
|
181
|
+
def SDL(s_loc:list,dir:list,l:float,n:int=1,id:int=None,group:str='',merge:bool=True):
|
|
182
|
+
if isinstance(s_loc,Node):
|
|
183
|
+
s_loc = (s_loc.X,s_loc.Y,s_loc.Z)
|
|
184
|
+
|
|
185
|
+
beam_nodes =[]
|
|
186
|
+
s_locc = np.array(s_loc)
|
|
187
|
+
unit_vec = np.array(dir)/np.linalg.norm(dir)
|
|
188
|
+
|
|
189
|
+
for i in range(n+1):
|
|
190
|
+
locc = s_locc+i*l*unit_vec/n
|
|
191
|
+
beam_nodes.append(Node(locc[0].item(),locc[1].item(),locc[2].item(),id,group,merge))
|
|
192
|
+
|
|
193
|
+
return beam_nodes
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# ---- GET NODE OBJECT FROM ID ----------
|
|
201
|
+
|
|
202
|
+
# def nodeByID(nodeID:int) -> Node:
|
|
203
|
+
# ''' Return Node object with the input ID '''
|
|
204
|
+
# for node in Node.nodes:
|
|
205
|
+
# if node.ID == nodeID:
|
|
206
|
+
# return node
|
|
207
|
+
|
|
208
|
+
# print(f'There is no node with ID {nodeID}')
|
|
209
|
+
# return None
|
|
210
|
+
|
|
211
|
+
def nodesInGroup(groupName:str,unique:bool=True,reverse:bool=False,output:Literal['ID','NODE']='ID') -> list[Node]:
|
|
212
|
+
''' Returns Node ID list or Node objects in a Structure Group or list of Structure groups
|
|
213
|
+
eg. nodesInGroup('SG_A')
|
|
214
|
+
nodesInGroup(['SG_1','SG_2','SG_3'])
|
|
215
|
+
groupName : 'SG_A' or ['SG_1' , 'SG_2' , 'SG_2']
|
|
216
|
+
unique : True -> Only unique ID is returned.
|
|
217
|
+
In case of multiple groups, we may require only uniques ids
|
|
218
|
+
reverse : True -> Reverses the returned list
|
|
219
|
+
'''
|
|
220
|
+
groupNames = _convItem2List(groupName)
|
|
221
|
+
nlist = []
|
|
222
|
+
for gName in groupNames:
|
|
223
|
+
chk=1
|
|
224
|
+
rev = reverse
|
|
225
|
+
if gName[0] == '!':
|
|
226
|
+
gName = gName[1:]
|
|
227
|
+
rev = not rev
|
|
228
|
+
for i in Group.Structure.Groups:
|
|
229
|
+
if i.NAME == gName:
|
|
230
|
+
chk=0
|
|
231
|
+
nIDlist = i.NLIST
|
|
232
|
+
if rev: nIDlist = list(reversed(nIDlist))
|
|
233
|
+
nlist.append(nIDlist)
|
|
234
|
+
if chk:
|
|
235
|
+
print(f'⚠️ "{gName}" - Structure group not found !')
|
|
236
|
+
if unique:
|
|
237
|
+
finalNlist = list(dict.fromkeys(sFlatten(nlist)))
|
|
238
|
+
else:
|
|
239
|
+
finalNlist = sFlatten(nlist)
|
|
240
|
+
|
|
241
|
+
if output == 'NODE':
|
|
242
|
+
finoutput = []
|
|
243
|
+
for nod in finalNlist:
|
|
244
|
+
finoutput.append(nodeByID(nod))
|
|
245
|
+
finalNlist:Node = finoutput
|
|
246
|
+
|
|
247
|
+
return finalNlist
|
|
248
|
+
|
|
249
|
+
def nodeByID(nodeID:int) -> Node:
|
|
250
|
+
''' Return Node object with the input ID '''
|
|
251
|
+
try:
|
|
252
|
+
return (Node.__nodeDic__[str(nodeID)])
|
|
253
|
+
except:
|
|
254
|
+
print(f'There is no node with ID {nodeID}')
|
|
255
|
+
return None
|
|
256
|
+
|
|
257
|
+
def closestNode(point_location:list) -> Node:
|
|
258
|
+
''' Enter location to find nearest node
|
|
259
|
+
list [x,y,z] => point location => Nearest node
|
|
260
|
+
node object => nearest remaining node
|
|
261
|
+
int => node with ID provided => nearest remaining node
|
|
262
|
+
'''
|
|
263
|
+
gridStr = list(Node.Grid.keys())
|
|
264
|
+
gridInt = []
|
|
265
|
+
for key in gridStr:
|
|
266
|
+
gridInt.append([int(x) for x in key.split(",")])
|
|
267
|
+
|
|
268
|
+
bNode = False
|
|
269
|
+
bNodeID = 0
|
|
270
|
+
if isinstance(point_location,int):
|
|
271
|
+
bNode = True
|
|
272
|
+
bNodeID = point_location
|
|
273
|
+
nodeP = nodeByID(point_location)
|
|
274
|
+
point_location = (nodeP.X,nodeP.Y,nodeP.Z)
|
|
275
|
+
elif isinstance(point_location,Node):
|
|
276
|
+
bNode = True
|
|
277
|
+
bNodeID = point_location.ID
|
|
278
|
+
point_location = (point_location.X,point_location.Y,point_location.Z)
|
|
279
|
+
pGridInt = [int(point_location[0]),int(point_location[1]),int(point_location[2])]
|
|
280
|
+
pGridStr = f"{int(point_location[0])},{int(point_location[1])},{int(point_location[2])}"
|
|
281
|
+
|
|
282
|
+
min_edge_dist = round(min(point_location[0]-pGridInt[0],point_location[1]-pGridInt[1],point_location[2]-pGridInt[2]),3)
|
|
283
|
+
max_edge_dist = round(max(point_location[0]-pGridInt[0],point_location[1]-pGridInt[1],point_location[2]-pGridInt[2]),3)
|
|
284
|
+
|
|
285
|
+
if min_edge_dist > 0.5 : min_edge_dist = round(1-min_edge_dist,3)
|
|
286
|
+
if max_edge_dist > 0.5 : max_edge_dist = round(1-max_edge_dist,3)
|
|
287
|
+
|
|
288
|
+
min_edge_dist = min(min_edge_dist,max_edge_dist)
|
|
289
|
+
|
|
290
|
+
min_dist = 10000000000 #Large value for initial value
|
|
291
|
+
min_node = 0
|
|
292
|
+
checked_GridInt = []
|
|
293
|
+
|
|
294
|
+
if bNode and len(Node.Grid[pGridStr]) == 1:
|
|
295
|
+
gridDist = []
|
|
296
|
+
for gInt in gridInt:
|
|
297
|
+
gridDist.append(abs(gInt[0]-pGridInt[0])+abs(gInt[1]-pGridInt[1])+abs(gInt[2]-pGridInt[2]))
|
|
298
|
+
gridDistSort = sorted(gridDist)
|
|
299
|
+
|
|
300
|
+
nearestGridIdx = gridDist.index(gridDistSort[1])
|
|
301
|
+
nearestGridInt = gridInt[nearestGridIdx]
|
|
302
|
+
nearestGridStr = gridStr[nearestGridIdx]
|
|
303
|
+
else:
|
|
304
|
+
if pGridInt in gridInt :
|
|
305
|
+
nearestGridInt = pGridInt
|
|
306
|
+
nearestGridStr = pGridStr
|
|
307
|
+
else :
|
|
308
|
+
gridDist = []
|
|
309
|
+
for gInt in gridInt:
|
|
310
|
+
gridDist.append(abs(gInt[0]-pGridInt[0])+abs(gInt[1]-pGridInt[1])+abs(gInt[2]-pGridInt[2]))
|
|
311
|
+
|
|
312
|
+
nearestGridIdx = gridDist.index(min(gridDist))
|
|
313
|
+
nearestGridInt = gridInt[nearestGridIdx]
|
|
314
|
+
nearestGridStr = gridStr[nearestGridIdx]
|
|
315
|
+
|
|
316
|
+
for nd in Node.Grid[nearestGridStr]:
|
|
317
|
+
dist = hypot(nd.X-point_location[0],nd.Y-point_location[1],nd.Z-point_location[2])
|
|
318
|
+
if dist < min_dist and nd.ID !=bNodeID:
|
|
319
|
+
min_dist = dist
|
|
320
|
+
min_node = nd
|
|
321
|
+
checked_GridInt.append(nearestGridInt)
|
|
322
|
+
if min_dist < min_edge_dist :
|
|
323
|
+
return min_node
|
|
324
|
+
|
|
325
|
+
else:
|
|
326
|
+
# COMBINATION POSSIBLE FOR CELLS
|
|
327
|
+
minX = int(point_location[0]-min_dist)
|
|
328
|
+
maxX = int(point_location[0]+min_dist)
|
|
329
|
+
minY = int(point_location[1]-min_dist)
|
|
330
|
+
maxY = int(point_location[1]+min_dist)
|
|
331
|
+
minZ = int(point_location[2]-min_dist)
|
|
332
|
+
maxZ = int(point_location[2]+min_dist)
|
|
333
|
+
possible = maxX+maxY+maxZ-minX-minY-minZ
|
|
334
|
+
if possible == 0:
|
|
335
|
+
return min_node
|
|
336
|
+
|
|
337
|
+
for i in np.arange(minX,maxX+1,1):
|
|
338
|
+
for j in np.arange(minY,maxY+1,1):
|
|
339
|
+
for k in np.arange(minZ,maxZ+1,1):
|
|
340
|
+
cgridStr = f"{i},{j},{k}"
|
|
341
|
+
cgridInt = [i,j,k]
|
|
342
|
+
|
|
343
|
+
if cgridInt in checked_GridInt:
|
|
344
|
+
continue
|
|
345
|
+
else:
|
|
346
|
+
if cgridInt in gridInt:
|
|
347
|
+
for nd in Node.Grid[cgridStr]:
|
|
348
|
+
dist = hypot(nd.X-point_location[0],nd.Y-point_location[1],nd.Z-point_location[2])
|
|
349
|
+
if dist < min_dist and nd.ID !=bNodeID:
|
|
350
|
+
min_dist = dist
|
|
351
|
+
min_node = nd
|
|
352
|
+
checked_GridInt.append(cgridInt)
|
|
353
|
+
return min_node
|
|
354
|
+
|
|
355
|
+
def _ifNodeExist_(x,y,z) -> tuple:
|
|
356
|
+
cell_loc = str(f"{int(x)},{int(y)},{int(z)}")
|
|
357
|
+
if cell_loc in Node.Grid:
|
|
358
|
+
for node in Node.Grid[cell_loc]:
|
|
359
|
+
if hypot((x-node.X),(y-node.Y),(z-node.Z)) < 0.00001 :
|
|
360
|
+
return True,node.ID
|
|
361
|
+
return False,0
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def nodesInRadius(point_location:list , radius:float=0, output :Literal['ID','NODE'] = 'ID',includeSelf = False)-> list:
|
|
365
|
+
gridStr = list(Node.Grid.keys())
|
|
366
|
+
|
|
367
|
+
bNode = False
|
|
368
|
+
id2Remove = 0
|
|
369
|
+
if isinstance(point_location,int):
|
|
370
|
+
bNode = True
|
|
371
|
+
id2Remove = point_location
|
|
372
|
+
nodeP = nodeByID(point_location)
|
|
373
|
+
point_location = (nodeP.X,nodeP.Y,nodeP.Z)
|
|
374
|
+
|
|
375
|
+
elif isinstance(point_location,Node):
|
|
376
|
+
bNode = True
|
|
377
|
+
id2Remove = point_location.ID
|
|
378
|
+
point_location = (point_location.X,point_location.Y,point_location.Z)
|
|
379
|
+
|
|
380
|
+
if not includeSelf and not bNode:
|
|
381
|
+
bNode,id2Remove = _ifNodeExist_(point_location[0],point_location[1],point_location[2])
|
|
382
|
+
|
|
383
|
+
ifRemove = bNode and not includeSelf
|
|
384
|
+
|
|
385
|
+
checked_GridStr = []
|
|
386
|
+
close_nodes:list[int] = []
|
|
387
|
+
close_nodesID:list[Node] = []
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
minX = int(point_location[0]-radius)
|
|
391
|
+
maxX = int(point_location[0]+radius)
|
|
392
|
+
minY = int(point_location[1]-radius)
|
|
393
|
+
maxY = int(point_location[1]+radius)
|
|
394
|
+
minZ = int(point_location[2]-radius)
|
|
395
|
+
maxZ = int(point_location[2]+radius)
|
|
396
|
+
|
|
397
|
+
for i in np.arange(minX,maxX+1,1):
|
|
398
|
+
for j in np.arange(minY,maxY+1,1):
|
|
399
|
+
for k in np.arange(minZ,maxZ+1,1):
|
|
400
|
+
cgridStr = f"{i},{j},{k}"
|
|
401
|
+
if cgridStr in checked_GridStr:
|
|
402
|
+
# print("Grid already checked")
|
|
403
|
+
continue
|
|
404
|
+
else:
|
|
405
|
+
if cgridStr in gridStr:
|
|
406
|
+
for nd in Node.Grid[cgridStr]:
|
|
407
|
+
dist = hypot(nd.X-point_location[0],nd.Y-point_location[1],nd.Z-point_location[2])
|
|
408
|
+
if dist <= radius+0.0001 :
|
|
409
|
+
close_nodes.append(nd)
|
|
410
|
+
close_nodesID.append(nd.ID)
|
|
411
|
+
checked_GridStr.append(cgridStr)
|
|
412
|
+
|
|
413
|
+
if output == 'Node':
|
|
414
|
+
if ifRemove:
|
|
415
|
+
close_nodes.remove(nodeByID(id2Remove))
|
|
416
|
+
return close_nodes
|
|
417
|
+
if ifRemove:
|
|
418
|
+
close_nodesID.remove(id2Remove)
|
|
419
|
+
return close_nodesID
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
class NodeLocalAxis:
|
|
424
|
+
skew = []
|
|
425
|
+
ids = []
|
|
426
|
+
|
|
427
|
+
def __init__(self,nodeID:int,type:Literal['X' , 'Y' , 'Z' , 'XYZ','Vector'],angle:list):
|
|
428
|
+
'''
|
|
429
|
+
nodeID(int) : ID of the node
|
|
430
|
+
axis (str) : Axis of rotation, 'X' , 'Y' , 'Z' , 'XYZ' or 'Vector'
|
|
431
|
+
angle (float) : Angle of rotation if axis = 'X' , 'Y' or 'Z' ;
|
|
432
|
+
angle (list : float) = [30,0,0] if type = 'XYZ'
|
|
433
|
+
angle (list : vector) -> node.AXIS = [[1,0,0],[0,1,0]] if type = 'Vector'
|
|
434
|
+
'''
|
|
435
|
+
|
|
436
|
+
self.ID = nodeID
|
|
437
|
+
|
|
438
|
+
if nodeID in NodeLocalAxis.ids:
|
|
439
|
+
index = NodeLocalAxis.ids.index(nodeID)
|
|
440
|
+
intial_angle = NodeLocalAxis.skew[index].ANGLE
|
|
441
|
+
if intial_angle == [[0,0,0],[0,0,0],[0,0,0]]:
|
|
442
|
+
intial_angle = [[1,0,0],[0,1,0],[0,0,1]]
|
|
443
|
+
|
|
444
|
+
if type == 'Vector':
|
|
445
|
+
self.TYPE = 'VEC'
|
|
446
|
+
self.VEC = angle
|
|
447
|
+
elif type == 'X':
|
|
448
|
+
self.TYPE = 'ANGLE'
|
|
449
|
+
self.ANGLE = [angle,intial_angle[1],intial_angle[2]]
|
|
450
|
+
elif type == 'Y':
|
|
451
|
+
self.TYPE = 'ANGLE'
|
|
452
|
+
self.ANGLE = [intial_angle[0],angle,intial_angle[2]]
|
|
453
|
+
elif type == 'Z':
|
|
454
|
+
self.TYPE = 'ANGLE'
|
|
455
|
+
self.ANGLE = [intial_angle[0],intial_angle[1],angle]
|
|
456
|
+
elif type == 'XYZ':
|
|
457
|
+
self.TYPE = 'ANGLE'
|
|
458
|
+
self.ANGLE = angle
|
|
459
|
+
NodeLocalAxis.skew[index] = self
|
|
460
|
+
else:
|
|
461
|
+
if type == 'Vector':
|
|
462
|
+
self.TYPE = 'VEC'
|
|
463
|
+
self.VEC = angle
|
|
464
|
+
self.ANGLE = [0,0,0]
|
|
465
|
+
elif type == 'X':
|
|
466
|
+
self.TYPE = 'ANGLE'
|
|
467
|
+
self.ANGLE = [angle,0,0]
|
|
468
|
+
elif type == 'Y':
|
|
469
|
+
self.TYPE = 'ANGLE'
|
|
470
|
+
self.ANGLE = [0,angle,0]
|
|
471
|
+
elif type == 'Z':
|
|
472
|
+
self.TYPE = 'ANGLE'
|
|
473
|
+
self.ANGLE = [0,0,angle]
|
|
474
|
+
elif type == 'XYZ':
|
|
475
|
+
self.TYPE = 'ANGLE'
|
|
476
|
+
self.ANGLE = angle
|
|
477
|
+
|
|
478
|
+
NodeLocalAxis.skew.append(self)
|
|
479
|
+
NodeLocalAxis.ids.append(self.ID)
|
|
480
|
+
|
|
481
|
+
@classmethod
|
|
482
|
+
def json(cls):
|
|
483
|
+
json = {"Assign":{}}
|
|
484
|
+
for i in cls.skew:
|
|
485
|
+
if i.TYPE == 'ANGLE':
|
|
486
|
+
json["Assign"][i.ID]={
|
|
487
|
+
"iMETHOD": 1,
|
|
488
|
+
"ANGLE_X": i.ANGLE[0],
|
|
489
|
+
"ANGLE_Y": i.ANGLE[1],
|
|
490
|
+
"ANGLE_Z": i.ANGLE[2]
|
|
491
|
+
}
|
|
492
|
+
elif i.TYPE == 'VEC':
|
|
493
|
+
json["Assign"][i.ID]={
|
|
494
|
+
"iMETHOD": 3,
|
|
495
|
+
"V1X": i.VEC[0][0],
|
|
496
|
+
"V1Y": i.VEC[0][1],
|
|
497
|
+
"V1Z": i.VEC[0][2],
|
|
498
|
+
"V2X": i.VEC[1][0],
|
|
499
|
+
"V2Y": i.VEC[1][1],
|
|
500
|
+
"V2Z": i.VEC[1][2]
|
|
501
|
+
}
|
|
502
|
+
return json
|
|
503
|
+
|
|
504
|
+
@staticmethod
|
|
505
|
+
def create():
|
|
506
|
+
MidasAPI("PUT","/db/SKEW",NodeLocalAxis.json())
|
|
507
|
+
|
|
508
|
+
@staticmethod
|
|
509
|
+
def delete():
|
|
510
|
+
MidasAPI("DELETE","/db/SKEW/")
|
|
511
|
+
NodeLocalAxis.clear()
|
|
512
|
+
|
|
513
|
+
@staticmethod
|
|
514
|
+
def clear():
|
|
515
|
+
NodeLocalAxis.skew=[]
|
|
516
|
+
NodeLocalAxis.ids=[]
|
|
517
|
+
|
|
518
|
+
@staticmethod
|
|
519
|
+
def get():
|
|
520
|
+
return MidasAPI("GET","/db/SKEW")
|
|
521
|
+
|
|
522
|
+
# @staticmethod
|
|
523
|
+
# def sync():
|
|
524
|
+
# NodeLocalAxis.skew=[]
|
|
525
|
+
# NodeLocalAxis.ids=[]
|
|
526
|
+
# a = NodeLocalAxis.get()
|
|
527
|
+
# if a != {'message': ''}:
|
|
528
|
+
# if list(a['NODE'].keys()) != []:
|
|
529
|
+
|
|
530
|
+
# for j in a['NODE'].keys():
|
|
531
|
+
|
|
532
|
+
# Node(round(a['NODE'][j]['X'],6), round(a['NODE'][j]['Y'],6), round(a['NODE'][j]['Z'],6), id=int(j), group='', merge=0)
|