Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions openstaad/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def __init__(self):

self._functions= [
'PerformAnalysis',
'CreateSteelDesignCommand'
]

for function_name in self._functions:
Expand All @@ -25,3 +26,20 @@ def PerformAnalysis(self,print_option:int):
--> 0 - No Print
"""
self._command.PerformAnalysis(print_option)

def CreateSteelDesignCommand(self,design_code:int, command_no:int,int_values:list[int],float_values:float,string_values:str,member_list:list[int]):

def make_safe_array_long(array):
size = len(array)
return automation._midlSAFEARRAY(ctypes.c_long).create(array)

safe_list_members = make_safe_array_long(member_list)
member_list = make_variant_vt_ref(safe_list_members, automation.VT_ARRAY | automation.VT_I4)

safe_list_int = make_safe_array_long(int_values)
int_values = make_variant_vt_ref(safe_list_int, automation.VT_ARRAY | automation.VT_I4)

self._command.CreateSteelDesignCommand(design_code,command_no,int_values,float_values,string_values,member_list)



124 changes: 89 additions & 35 deletions openstaad/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,43 +11,54 @@ def __init__(self):
self._geometry = self._staad.Geometry

self._functions= [
"AddBeam",
"AddNode",
"ClearMemberSelection",
"CreatePhysicalMember",
"DeletePhysicalMember",
"DoTranslationalRepeat",
"GetAnalyticalMemberCountForPhysicalMember",
"GetAnalyticalMembersForPhysicalMember",
"GetBeamLength",
"GetBeamList",
"GetBeamsConnectedAtNode",
"GetGroupCount",
"GetGroupEntities",
"GetGroupEntityCount",
"GetGroupNames",
"GetIntersectBeamsCount",
"GetLastBeamNo",
"GetLastNodeNo",
"GetLastPhysicalMemberNo",
"GetMemberCount",
"GetMemberIncidence",
"GetNodeCoordinates",
"GetNodeCount",
"GetNodeDistance",
"GetNodeIncidence",
"GetNodeList",
"GetNodeNumber",
"GetNoOfBeamsConnectedAtNode",
"GetNoOfSelectedBeams",
"GetNoOfSelectedNodes",
"GetNoOfSelectedPhysicalMembers",
"GetPMemberCount",
"GetPhysicalMemberCount",
"GetPhysicalMemberList",
"GetPhysicalMemberUniqueID",
"GetSelectedBeams",
"GetSelectedNodes",
'GetBeamLength',
'GetBeamList',
'GetMemberCount',
'GetLastBeamNo',
'GetMemberIncidence',
'GetNoOfSelectedBeams',
'GetSelectedBeams',
'GetNoOfBeamsConnectedAtNode',
'GetBeamsConnectedAtNode',
'GetGroupEntities',
'GetGroupEntityCount',
'ClearMemberSelection',
'SelectMultipleBeams',
'GetGroupCount',
'GetGroupNames',
'CreatePhysicalMember',
'AddNode',
'AddBeam',
'DoTranslationalRepeat',
'GetIntersectBeamsCount',
'IntersectBeams'
"GetSelectedPhysicalMembers",
"IntersectBeams",
"SelectMultipleBeams",
"SelectMultiplePhysicalMembers",
"SelectPhysicalMember",
"SetPhysicalMemberUniqueID"
]

for function_name in self._functions:
self._geometry._FlagAsMethod(function_name)

## NODE FUNCTIONS

def GetLastNodeNo(self):
return self._geometry.GetLastNodeNo()

Expand Down Expand Up @@ -119,8 +130,6 @@ def GetSelectedNodes(self):
self._geometry.GetSelectedNodes(lista)

return (lista[0])

## BEAM FUNCTIONS

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

return list[0]

## GROUP FUNCTIONS

def GetGroupEntityCount(self,group_name):
return self._geometry.GetGroupEntityCount(group_name)

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



def AddNode(self,x:float=0.0,y:float=0.0,z:float=0.0):
retval=self._geometry.AddNode(x,y,z)
return retval

def AddBeam(self,node_A,node_B):
retval=self._geometry.AddBeam(node_A,node_B)
return retval

def DeletePhysicalMember(self,p_member:int):
self._geometry.DeletePhysicalMember(p_member)

def GetAnalyticalMemberCountForPhysicalMember(self,p_member:int):
return self._geometry.GetAnalyticalMemberCountForPhysicalMember(p_member)

def make_safe_array_long(data):
if not isinstance(data, list):
raise TypeError("Data must be a list of integers")
Expand All @@ -257,7 +268,7 @@ def make_variant_vt_ref(safe_array, vt_type):
variant.vt = vt_type
variant._.parray = safe_array
return variant

def DoTranslationalRepeat(self, varLinkBays: bool, varOpenBase: bool, varAxisDir: int, varSpacingArray: list[float], varNobays: int, varRenumberBay: bool, varRenumberArray: list, varGeometryOnly: bool):
try:

Expand All @@ -274,7 +285,7 @@ def make_safe_array_double(array):
except Exception as e:
print(f"An error occurred in DoTranslationalRepeat: {e}")
raise

def IntersectBeams(self, Method: int, BeamNosArray: list[int], dTolerance: float, NewBeamNosArray: int):

# Conversión de dTolerance
Expand All @@ -298,7 +309,7 @@ def make_safe_array_long(array):
# Llamada a la función interna
retval = self._geometry.IntersectBeams(Method, BeamNosArray, dTolerance, NewBeamNosArray)
return retval

def GetIntersectBeamsCount(self, BeamNosArray: list[int], dTolerance: float):
safe_n1 = make_safe_array_double(1)
dTolerance = make_variant_vt_ref(safe_n1, automation.VT_R8)
Expand All @@ -312,8 +323,51 @@ def make_safe_array_long(array):

n_beams = self._geometry.GetIntersectBeamsCount(BeamNosArray, dTolerance)
return n_beams



#Not Working yet
def GetAnalyticalMembersForPhysicalMember(self, p_member: int):

no_am = self._geometry.GetAnalyticalMemberCountForPhysicalMember(p_member)

if no_am == 0:
return []

safe_list = automation._midlSAFEARRAY(ctypes.c_int).create([0] * no_am)

var_p_member = automation.VARIANT(p_member)
var_no_am = automation.VARIANT(no_am)
var_member_list = automation.VARIANT()
var_member_list._.c_void_p = ctypes.addressof(safe_list)
var_member_list.vt = automation.VT_ARRAY | automation.VT_I4 | automation.VT_BYREF

self._geometry.GetAnalyticalMembersForPhysicalMember(
var_p_member, var_no_am, var_member_list
)

return list(safe_list)

def GetLastPhysicalMemberNo(self):
return self._geometry.GetLastPhysicalMemberNo()

def GetNoOfSelectedPhysicalMembers(self):
return self._geometry.GetNoOfSelectedPhysicalMembers()

def GetPhysicalMemberCount(self):
return self._geometry.GetPhysicalMemberCount()

def GetPhysicalMemberList(self):
no_p_members=self._geometry.GetPhysicalMemberCount()

safe_list = make_safe_array_long(no_p_members)
lista = make_variant_vt_ref(safe_list, automation.VT_ARRAY | automation.VT_I4)

self._geometry.GetPhysicalMemberList(lista)

return (lista[0])

def GetPhysicalMemberUniqueID(self,p_member):
return self._geometry.GetPhysicalMemberUniqueID(p_member)

def GetPMemberCount(self):
return self._geometry.GetPMemberCount()

148 changes: 136 additions & 12 deletions openstaad/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,155 @@ def __init__(self):
self._load = self._staad.Load

self._functions= [
'GetLoadCaseTitle',
'AddMemberConcForce',
'SetLoadActive',
'CreateNewPrimaryLoad'
"AddMemberConcForce",
"AddResponseSpectrumLoadEx",
"AddSelfWeightInXYZ",
"AddWindDefinition",
"ClearPrimaryLoadCase",
"CreateNewPrimaryLoad",
"CreateNewReferenceLoad",
"DeleteDirectAnalysisDefinition",
"DeleteDirectAnalysisDefinitionParameter",
"DeleteWindDefinition",
"GetLoadCaseTitle",
"GetReferenceLoadCaseCount",
"SetLoadActive",
"SetReferenceLoadActive"
]

for function_name in self._functions:
self._load._FlagAsMethod(function_name)

def GetLoadCaseTitle(self,lc):
return self._load.GetLoadCaseTitle(lc)

def AddMemberConcForce(self,varBeamNo:list[int],varDirection:int,varForce:float,varD1:float,varD2:float):

"""
Adds CONCENTRATED FORCE to beam(s).
"""
def make_safe_array_long(array):
size = len(array)
return automation._midlSAFEARRAY(ctypes.c_long).create(array)

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

self._load.AddMemberConcForce(varBeamNo,varDirection,varForce,varD1,varD2)
return self._load.AddMemberConcForce(varBeamNo,varDirection,varForce,varD1,varD2)

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):
"""Adds Response Spectrum load item to the currently active load case.

Parameters
[in] code_number Response Spectrum Loading Code. Refer to the following table for the integers corresponding to different codes.
[in] modal_combination Modal combination rule. (SRSS = 0, ABS = 1, CQC = 2, ASCE = 3, TEN = 4, CSM = 5, GRP = 6)
[in] Set1Names VARIANT BSTR array containing parameter key words. Refer to the Techincal Reference sections as indicated below.
[in] Set1Vals Parameters values corresponding to the keywords supplied in varSet1Names array.
[in] Set2Names Optional VARIANT BSTR array containing parameter key words for the spectrum generation data command. NULL can be used if not neeed.
[in] Set2Vals Parameters values corresponding to the keywords supplied in varSet2Names array. NULL can be used if not needed.
[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.
"""
def make_safe_array_string1(values):
return automation._midlSAFEARRAY(automation.BSTR).create(values)

def make_safe_array_double1(values):
return automation._midlSAFEARRAY(ctypes.c_double).create(values)

def SetLoadActive(self,varLoadNo:int):
self._load.SetLoadActive(varLoadNo)
array_names_1 = make_safe_array_string1(set_names_1)
array_values_1 = make_safe_array_double1(set_values_1)

if spectrum_data_pairs is not None:
flat_spectrum = [val for pair in spectrum_data_pairs for val in pair]
arr_spectrum = make_safe_array_double1(flat_spectrum)
var_spectrum = make_variant_vt_ref(arr_spectrum, automation.VT_ARRAY | automation.VT_R8)
else:
var_spectrum = None

var_set2_names = None
var_set2_vals = None

var_set1_names = make_variant_vt_ref(array_names_1, automation.VT_ARRAY | automation.VT_BSTR)
var_set1_vals = make_variant_vt_ref(array_values_1, automation.VT_ARRAY | automation.VT_R8)

return self._load.AddResponseSpectrumLoadEx(code_number,modal_combination,var_set1_names,var_set1_vals,var_set2_names,var_set2_vals,var_spectrum)

def AddSelfWeightInXYZ(self, load_direction: int, load_factor: float):
"""
Adds a self weight to the active load case.
"""
v_direction = automation.VARIANT()
v_direction.value = load_direction

v_factor = automation.VARIANT()
v_factor.value = float(load_factor)

return self._load.AddSelfWeightInXYZ(v_direction, v_factor)

def AddWindDefinition(self,type_No:int,type_name:str):
"""
Adds a Wind Definition named type_name" with number ID type_No.
"""
return self._load.AddWindDefinition(type_No,type_name)

def ClearPrimaryLoadCase(self,load_case:int,is_reference_lc:bool=False):
"""
Clears the load items in a specified Primary Load cases or Reference Load cases.
"""
return self._load.ClearPrimaryLoadCase(load_case,is_reference_lc)

def CreateNewPrimaryLoad(self,LoadTitle:str="LOAD CASE X"):
self._load.CreateNewPrimaryLoad(LoadTitle)
"""
Creates new PRIMARY load case.
"""
return self._load.CreateNewPrimaryLoad(LoadTitle)

def CreateNewReferenceLoad(self,load_No:int,loadcase_title:str,load_type:int):
"""
Creates a new Reference Load Definition and set as active.
"""
return self._load.CreateNewReferenceLoad(load_No,loadcase_title,load_type)

def DeleteDirectAnalysisDefinition(self):
"""
Deletes whole Direct Analysis Definition.
"""
return self._load.DeleteDirectAnalysisDefinition()

def DeleteDirectAnalysisDefinitionParameter(self,parameter_type:int=0):
"""
Deletes respective parameters from Direct Analysis Definition based on the Parameter Type passed as argument (FLEX/AXIAL).
Flex --- 0
Axial --- 2
"""
return self._load.DeleteDirectAnalysisDefinitionParameter(parameter_type)

def DeleteWindDefinition(self,type_No:int=0):
"""
Deletes Wind definition. All definitions will be deleted if this input is set as 0.
"""
return self._load.DeleteWindDefinition(type_No)

def GetLoadCaseTitle(self,lc:int=0):
"""
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.
"""
return self._load.GetLoadCaseTitle(lc)

def GetReferenceLoadCaseCount(self):
"""
Returns the number of reference load case defined in Reference Load Definitions.
"""
return self._load.GetReferenceLoadCaseCount()

def SetLoadActive(self,load_case:int):
"""
Makes the specified load number active, in order to add or remove load item(s).
"""
return self._load.SetLoadActive(load_case)

def SetReferenceLoadActive(self,load_case:int):
"""
Identify a Load Case in Load Case Details to add, count and get reference load item(s).
"""
return self._load.SetReferenceLoadActive(load_case)





Loading