Skip to content

Commit 0ad5d29

Browse files
authored
Merge pull request #5 from cv/main
Several functions implemented , also order functions
2 parents 566bb6c + c48a506 commit 0ad5d29

9 files changed

Lines changed: 638 additions & 288 deletions

File tree

openstaad/command.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ def __init__(self):
99

1010
self._functions= [
1111
'PerformAnalysis',
12+
'CreateSteelDesignCommand'
1213
]
1314

1415
for function_name in self._functions:
@@ -25,3 +26,20 @@ def PerformAnalysis(self,print_option:int):
2526
--> 0 - No Print
2627
"""
2728
self._command.PerformAnalysis(print_option)
29+
30+
def CreateSteelDesignCommand(self,design_code:int, command_no:int,int_values:list[int],float_values:float,string_values:str,member_list:list[int]):
31+
32+
def make_safe_array_long(array):
33+
size = len(array)
34+
return automation._midlSAFEARRAY(ctypes.c_long).create(array)
35+
36+
safe_list_members = make_safe_array_long(member_list)
37+
member_list = make_variant_vt_ref(safe_list_members, automation.VT_ARRAY | automation.VT_I4)
38+
39+
safe_list_int = make_safe_array_long(int_values)
40+
int_values = make_variant_vt_ref(safe_list_int, automation.VT_ARRAY | automation.VT_I4)
41+
42+
self._command.CreateSteelDesignCommand(design_code,command_no,int_values,float_values,string_values,member_list)
43+
44+
45+

openstaad/geometry.py

Lines changed: 89 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,43 +11,54 @@ def __init__(self):
1111
self._geometry = self._staad.Geometry
1212

1313
self._functions= [
14+
"AddBeam",
15+
"AddNode",
16+
"ClearMemberSelection",
17+
"CreatePhysicalMember",
18+
"DeletePhysicalMember",
19+
"DoTranslationalRepeat",
20+
"GetAnalyticalMemberCountForPhysicalMember",
21+
"GetAnalyticalMembersForPhysicalMember",
22+
"GetBeamLength",
23+
"GetBeamList",
24+
"GetBeamsConnectedAtNode",
25+
"GetGroupCount",
26+
"GetGroupEntities",
27+
"GetGroupEntityCount",
28+
"GetGroupNames",
29+
"GetIntersectBeamsCount",
30+
"GetLastBeamNo",
1431
"GetLastNodeNo",
32+
"GetLastPhysicalMemberNo",
33+
"GetMemberCount",
34+
"GetMemberIncidence",
1535
"GetNodeCoordinates",
1636
"GetNodeCount",
1737
"GetNodeDistance",
1838
"GetNodeIncidence",
1939
"GetNodeList",
2040
"GetNodeNumber",
41+
"GetNoOfBeamsConnectedAtNode",
42+
"GetNoOfSelectedBeams",
2143
"GetNoOfSelectedNodes",
44+
"GetNoOfSelectedPhysicalMembers",
45+
"GetPMemberCount",
46+
"GetPhysicalMemberCount",
47+
"GetPhysicalMemberList",
48+
"GetPhysicalMemberUniqueID",
49+
"GetSelectedBeams",
2250
"GetSelectedNodes",
23-
'GetBeamLength',
24-
'GetBeamList',
25-
'GetMemberCount',
26-
'GetLastBeamNo',
27-
'GetMemberIncidence',
28-
'GetNoOfSelectedBeams',
29-
'GetSelectedBeams',
30-
'GetNoOfBeamsConnectedAtNode',
31-
'GetBeamsConnectedAtNode',
32-
'GetGroupEntities',
33-
'GetGroupEntityCount',
34-
'ClearMemberSelection',
35-
'SelectMultipleBeams',
36-
'GetGroupCount',
37-
'GetGroupNames',
38-
'CreatePhysicalMember',
39-
'AddNode',
40-
'AddBeam',
41-
'DoTranslationalRepeat',
42-
'GetIntersectBeamsCount',
43-
'IntersectBeams'
51+
"GetSelectedPhysicalMembers",
52+
"IntersectBeams",
53+
"SelectMultipleBeams",
54+
"SelectMultiplePhysicalMembers",
55+
"SelectPhysicalMember",
56+
"SetPhysicalMemberUniqueID"
4457
]
4558

4659
for function_name in self._functions:
4760
self._geometry._FlagAsMethod(function_name)
4861

49-
## NODE FUNCTIONS
50-
5162
def GetLastNodeNo(self):
5263
return self._geometry.GetLastNodeNo()
5364

@@ -119,8 +130,6 @@ def GetSelectedNodes(self):
119130
self._geometry.GetSelectedNodes(lista)
120131

121132
return (lista[0])
122-
123-
## BEAM FUNCTIONS
124133

125134
def GetBeamLength(self,beam):
126135
length = round(self._geometry.GetBeamLength(beam)*1000)/1000
@@ -181,8 +190,6 @@ def GetBeamsConnectedAtNode(self,node):
181190

182191
return list[0]
183192

184-
## GROUP FUNCTIONS
185-
186193
def GetGroupEntityCount(self,group_name):
187194
return self._geometry.GetGroupEntityCount(group_name)
188195

@@ -230,16 +237,20 @@ def CreatePhysicalMember(self,member_list:list):
230237
lista_variant = make_variant_vt_ref(safe_list, automation.VT_ARRAY | automation.VT_I4)
231238
retval=self._geometry.CreatePhysicalMember(num,lista_variant,None)
232239

233-
234-
235240
def AddNode(self,x:float=0.0,y:float=0.0,z:float=0.0):
236241
retval=self._geometry.AddNode(x,y,z)
237242
return retval
238-
243+
239244
def AddBeam(self,node_A,node_B):
240245
retval=self._geometry.AddBeam(node_A,node_B)
241246
return retval
247+
248+
def DeletePhysicalMember(self,p_member:int):
249+
self._geometry.DeletePhysicalMember(p_member)
242250

251+
def GetAnalyticalMemberCountForPhysicalMember(self,p_member:int):
252+
return self._geometry.GetAnalyticalMemberCountForPhysicalMember(p_member)
253+
243254
def make_safe_array_long(data):
244255
if not isinstance(data, list):
245256
raise TypeError("Data must be a list of integers")
@@ -257,7 +268,7 @@ def make_variant_vt_ref(safe_array, vt_type):
257268
variant.vt = vt_type
258269
variant._.parray = safe_array
259270
return variant
260-
271+
261272
def DoTranslationalRepeat(self, varLinkBays: bool, varOpenBase: bool, varAxisDir: int, varSpacingArray: list[float], varNobays: int, varRenumberBay: bool, varRenumberArray: list, varGeometryOnly: bool):
262273
try:
263274

@@ -274,7 +285,7 @@ def make_safe_array_double(array):
274285
except Exception as e:
275286
print(f"An error occurred in DoTranslationalRepeat: {e}")
276287
raise
277-
288+
278289
def IntersectBeams(self, Method: int, BeamNosArray: list[int], dTolerance: float, NewBeamNosArray: int):
279290

280291
# Conversión de dTolerance
@@ -298,7 +309,7 @@ def make_safe_array_long(array):
298309
# Llamada a la función interna
299310
retval = self._geometry.IntersectBeams(Method, BeamNosArray, dTolerance, NewBeamNosArray)
300311
return retval
301-
312+
302313
def GetIntersectBeamsCount(self, BeamNosArray: list[int], dTolerance: float):
303314
safe_n1 = make_safe_array_double(1)
304315
dTolerance = make_variant_vt_ref(safe_n1, automation.VT_R8)
@@ -312,8 +323,51 @@ def make_safe_array_long(array):
312323

313324
n_beams = self._geometry.GetIntersectBeamsCount(BeamNosArray, dTolerance)
314325
return n_beams
315-
316326

317-
327+
#Not Working yet
328+
def GetAnalyticalMembersForPhysicalMember(self, p_member: int):
329+
330+
no_am = self._geometry.GetAnalyticalMemberCountForPhysicalMember(p_member)
331+
332+
if no_am == 0:
333+
return []
334+
335+
safe_list = automation._midlSAFEARRAY(ctypes.c_int).create([0] * no_am)
336+
337+
var_p_member = automation.VARIANT(p_member)
338+
var_no_am = automation.VARIANT(no_am)
339+
var_member_list = automation.VARIANT()
340+
var_member_list._.c_void_p = ctypes.addressof(safe_list)
341+
var_member_list.vt = automation.VT_ARRAY | automation.VT_I4 | automation.VT_BYREF
342+
343+
self._geometry.GetAnalyticalMembersForPhysicalMember(
344+
var_p_member, var_no_am, var_member_list
345+
)
346+
347+
return list(safe_list)
348+
349+
def GetLastPhysicalMemberNo(self):
350+
return self._geometry.GetLastPhysicalMemberNo()
318351

352+
def GetNoOfSelectedPhysicalMembers(self):
353+
return self._geometry.GetNoOfSelectedPhysicalMembers()
319354

355+
def GetPhysicalMemberCount(self):
356+
return self._geometry.GetPhysicalMemberCount()
357+
358+
def GetPhysicalMemberList(self):
359+
no_p_members=self._geometry.GetPhysicalMemberCount()
360+
361+
safe_list = make_safe_array_long(no_p_members)
362+
lista = make_variant_vt_ref(safe_list, automation.VT_ARRAY | automation.VT_I4)
363+
364+
self._geometry.GetPhysicalMemberList(lista)
365+
366+
return (lista[0])
367+
368+
def GetPhysicalMemberUniqueID(self,p_member):
369+
return self._geometry.GetPhysicalMemberUniqueID(p_member)
370+
371+
def GetPMemberCount(self):
372+
return self._geometry.GetPMemberCount()
373+

openstaad/load.py

Lines changed: 136 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,155 @@ def __init__(self):
88
self._load = self._staad.Load
99

1010
self._functions= [
11-
'GetLoadCaseTitle',
12-
'AddMemberConcForce',
13-
'SetLoadActive',
14-
'CreateNewPrimaryLoad'
11+
"AddMemberConcForce",
12+
"AddResponseSpectrumLoadEx",
13+
"AddSelfWeightInXYZ",
14+
"AddWindDefinition",
15+
"ClearPrimaryLoadCase",
16+
"CreateNewPrimaryLoad",
17+
"CreateNewReferenceLoad",
18+
"DeleteDirectAnalysisDefinition",
19+
"DeleteDirectAnalysisDefinitionParameter",
20+
"DeleteWindDefinition",
21+
"GetLoadCaseTitle",
22+
"GetReferenceLoadCaseCount",
23+
"SetLoadActive",
24+
"SetReferenceLoadActive"
1525
]
1626

1727
for function_name in self._functions:
1828
self._load._FlagAsMethod(function_name)
1929

20-
def GetLoadCaseTitle(self,lc):
21-
return self._load.GetLoadCaseTitle(lc)
22-
2330
def AddMemberConcForce(self,varBeamNo:list[int],varDirection:int,varForce:float,varD1:float,varD2:float):
24-
31+
"""
32+
Adds CONCENTRATED FORCE to beam(s).
33+
"""
2534
def make_safe_array_long(array):
2635
size = len(array)
2736
return automation._midlSAFEARRAY(ctypes.c_long).create(array)
2837

2938
safe_list = make_safe_array_long(varBeamNo)
3039
varBeamNo = make_variant_vt_ref(safe_list, automation.VT_ARRAY | automation.VT_I4)
3140

32-
self._load.AddMemberConcForce(varBeamNo,varDirection,varForce,varD1,varD2)
41+
return self._load.AddMemberConcForce(varBeamNo,varDirection,varForce,varD1,varD2)
42+
43+
def AddResponseSpectrumLoadEx(self, code_number:int, modal_combination:int, set_names_1:list, set_values_1:list, spectrum_data_pairs:list[tuple],set_names_2:list=None, set_values_2:list=None):
44+
"""Adds Response Spectrum load item to the currently active load case.
45+
46+
Parameters
47+
[in] code_number Response Spectrum Loading Code. Refer to the following table for the integers corresponding to different codes.
48+
[in] modal_combination Modal combination rule. (SRSS = 0, ABS = 1, CQC = 2, ASCE = 3, TEN = 4, CSM = 5, GRP = 6)
49+
[in] Set1Names VARIANT BSTR array containing parameter key words. Refer to the Techincal Reference sections as indicated below.
50+
[in] Set1Vals Parameters values corresponding to the keywords supplied in varSet1Names array.
51+
[in] Set2Names Optional VARIANT BSTR array containing parameter key words for the spectrum generation data command. NULL can be used if not neeed.
52+
[in] Set2Vals Parameters values corresponding to the keywords supplied in varSet2Names array. NULL can be used if not needed.
53+
[in] DataPairs VARIANT double array containing pairs of time period and accleration data. NULL can used if not needed. Inputs (varSet2Names, varSet2Vals) and (varDataPairs) are mutually exclusive, i.e. if one is specified, other should not specified.
54+
"""
55+
def make_safe_array_string1(values):
56+
return automation._midlSAFEARRAY(automation.BSTR).create(values)
57+
58+
def make_safe_array_double1(values):
59+
return automation._midlSAFEARRAY(ctypes.c_double).create(values)
3360

34-
def SetLoadActive(self,varLoadNo:int):
35-
self._load.SetLoadActive(varLoadNo)
61+
array_names_1 = make_safe_array_string1(set_names_1)
62+
array_values_1 = make_safe_array_double1(set_values_1)
63+
64+
if spectrum_data_pairs is not None:
65+
flat_spectrum = [val for pair in spectrum_data_pairs for val in pair]
66+
arr_spectrum = make_safe_array_double1(flat_spectrum)
67+
var_spectrum = make_variant_vt_ref(arr_spectrum, automation.VT_ARRAY | automation.VT_R8)
68+
else:
69+
var_spectrum = None
70+
71+
var_set2_names = None
72+
var_set2_vals = None
3673

74+
var_set1_names = make_variant_vt_ref(array_names_1, automation.VT_ARRAY | automation.VT_BSTR)
75+
var_set1_vals = make_variant_vt_ref(array_values_1, automation.VT_ARRAY | automation.VT_R8)
76+
77+
return self._load.AddResponseSpectrumLoadEx(code_number,modal_combination,var_set1_names,var_set1_vals,var_set2_names,var_set2_vals,var_spectrum)
78+
79+
def AddSelfWeightInXYZ(self, load_direction: int, load_factor: float):
80+
"""
81+
Adds a self weight to the active load case.
82+
"""
83+
v_direction = automation.VARIANT()
84+
v_direction.value = load_direction
85+
86+
v_factor = automation.VARIANT()
87+
v_factor.value = float(load_factor)
88+
89+
return self._load.AddSelfWeightInXYZ(v_direction, v_factor)
90+
91+
def AddWindDefinition(self,type_No:int,type_name:str):
92+
"""
93+
Adds a Wind Definition named type_name" with number ID type_No.
94+
"""
95+
return self._load.AddWindDefinition(type_No,type_name)
96+
97+
def ClearPrimaryLoadCase(self,load_case:int,is_reference_lc:bool=False):
98+
"""
99+
Clears the load items in a specified Primary Load cases or Reference Load cases.
100+
"""
101+
return self._load.ClearPrimaryLoadCase(load_case,is_reference_lc)
102+
37103
def CreateNewPrimaryLoad(self,LoadTitle:str="LOAD CASE X"):
38-
self._load.CreateNewPrimaryLoad(LoadTitle)
104+
"""
105+
Creates new PRIMARY load case.
106+
"""
107+
return self._load.CreateNewPrimaryLoad(LoadTitle)
108+
109+
def CreateNewReferenceLoad(self,load_No:int,loadcase_title:str,load_type:int):
110+
"""
111+
Creates a new Reference Load Definition and set as active.
112+
"""
113+
return self._load.CreateNewReferenceLoad(load_No,loadcase_title,load_type)
114+
115+
def DeleteDirectAnalysisDefinition(self):
116+
"""
117+
Deletes whole Direct Analysis Definition.
118+
"""
119+
return self._load.DeleteDirectAnalysisDefinition()
120+
121+
def DeleteDirectAnalysisDefinitionParameter(self,parameter_type:int=0):
122+
"""
123+
Deletes respective parameters from Direct Analysis Definition based on the Parameter Type passed as argument (FLEX/AXIAL).
124+
Flex --- 0
125+
Axial --- 2
126+
"""
127+
return self._load.DeleteDirectAnalysisDefinitionParameter(parameter_type)
128+
129+
def DeleteWindDefinition(self,type_No:int=0):
130+
"""
131+
Deletes Wind definition. All definitions will be deleted if this input is set as 0.
132+
"""
133+
return self._load.DeleteWindDefinition(type_No)
134+
135+
def GetLoadCaseTitle(self,lc:int=0):
136+
"""
137+
Returns title of the specified load case as a text string. Input 0 to retrieve title of current active load case or reference load case.
138+
"""
139+
return self._load.GetLoadCaseTitle(lc)
140+
141+
def GetReferenceLoadCaseCount(self):
142+
"""
143+
Returns the number of reference load case defined in Reference Load Definitions.
144+
"""
145+
return self._load.GetReferenceLoadCaseCount()
146+
147+
def SetLoadActive(self,load_case:int):
148+
"""
149+
Makes the specified load number active, in order to add or remove load item(s).
150+
"""
151+
return self._load.SetLoadActive(load_case)
152+
153+
def SetReferenceLoadActive(self,load_case:int):
154+
"""
155+
Identify a Load Case in Load Case Details to add, count and get reference load item(s).
156+
"""
157+
return self._load.SetReferenceLoadActive(load_case)
158+
159+
160+
161+
162+

0 commit comments

Comments
 (0)