-
Notifications
You must be signed in to change notification settings - Fork 12
/
points.py
131 lines (120 loc) · 4.64 KB
/
points.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from typing import Iterable, Union
import math
class Points:
def __init__(
self,
SapModel=None,
etabs=None,
):
if not SapModel:
self.etabs = etabs
self.SapModel = etabs.SapModel
else:
self.SapModel = SapModel
def set_point_restraint(self,
point_names,
restraint: list= [True, True, False, False, False, False]):
for point_name in point_names:
self.SapModel.PointObj.SetRestraint(point_name, restraint)
def get_distance_between_two_points_in_XY(self,
p1 : Union[str, tuple],
p2 : Union[str, tuple],
) -> float:
if isinstance(p1, tuple):
x1, y1 = p1
else:
x1, y1 = self.SapModel.PointObj.GetCoordCartesian(p1)[:2]
if isinstance(p2, tuple):
x2, y2 = p2
else:
x2, y2 = self.SapModel.PointObj.GetCoordCartesian(p2)[:2]
d = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
return d
def get_points_coords(self, points : Iterable):
points_xyz = {}
for p in points:
x, y, z, _ = self.SapModel.PointObj.GetCoordCartesian(p)
points_xyz[p] = (x, y, z)
return points_xyz
def add_point(self,
x: float,
y: float,
z: float,
unlock_model: bool=True,
):
if unlock_model:
self.etabs.unlock_model()
name = self.SapModel.PointObj.AddCartesian(float(x), float(y), float(z))[0]
return name
def add_point_on_beam(self,
name: str,
distance: Union[str, float]='middle', #start, end
unlock_model: bool=True,
):
p1_name, p2_name, _ = self.SapModel.FrameObj.GetPoints(name)
x1, y1, z1 = self.SapModel.PointObj.GetCoordCartesian(p1_name)[:3]
x2, y2, z2 = self.SapModel.PointObj.GetCoordCartesian(p2_name)[:3]
length = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2 + (z2 - z1) ** 2)
if type(distance) == str:
if distance == 'middle':
distance = length / 2
rel = distance / length
x = (x2 - x1) * rel + x1
y = (y2 - y1) * rel + y1
z = (z2 - z1) * rel + z1
return self.add_point(x, y, z, unlock_model=unlock_model)
def get_points_coordinates(self,
points: list=[],
to_dict: bool=False,
):
'''
return a dataframe with point_name and x, y, z coordinate,
or a dictionary like {'10': (0, 0, 0), ...}
'''
table_key = 'Point Object Connectivity'
cols = ['UniqueName', 'X', 'Y', 'Z']
df = self.etabs.database.read(table_key, to_dataframe=True, cols=cols)
if points:
filt = df['UniqueName'].isin(points)
df = df.loc[filt]
df = df.astype({'UniqueName': int, 'X': float, 'Y': float, 'Z': float})
if to_dict:
return df.set_index("UniqueName").apply(tuple, axis=1).to_dict()
else:
return df
def get_objects_and_elements_joints_coordinate(self,
types: list=[], # [Joint, Shell]
unit: str = 'mm',
to_dict: bool=True,
map_dict: dict={},
joints: Iterable=[],
) -> dict:
'''
map_dict: A dictionary for mapping mesh points name to int point name
Return all joints coordinates in FEM, include mesh joints
'''
force, length = self.etabs.get_current_unit()
self.etabs.set_current_unit(force, unit)
self.etabs.run_analysis()
table_key = 'Objects and Elements - Joints'
cols = ['ObjType', 'ElmName', 'GlobalX', 'GlobalY', 'GlobalZ']
df = self.etabs.database.read(table_key=table_key, to_dataframe=True, cols=cols)
if joints:
df = df[df['ElmName'].isin(joints)]
if types:
df = df[df['ObjType'].isin(types)]
del df['ObjType']
df = df.astype({'GlobalX': float, 'GlobalY': float, 'GlobalZ': float, })
self.etabs.set_current_unit(force, length)
if map_dict:
col = 'ElmName'
df[col] = df[col].map(map_dict).fillna(df[col])
df[col] = df[col].astype(int)
if to_dict:
return df.set_index("ElmName").apply(tuple, axis=1).to_dict()
else:
return df
def get_maximum_point_number_in_model(self):
df = self.get_points_coordinates()
max_number = df.UniqueName.max()
return max_number