def generate_truss_by_grid(grid, enabled): """ enabled is a list of booleans indicating which members in the grid are enabled. Length must match the total possible members in the grid """ enabled = np.array(enabled) width = MIN_WIDTH / 2 height = MAX_HEIGHT all_possible_members = grid # print(f"number of possible members: {len(all_possible_members)}") assert len(all_possible_members) == len(enabled) members = all_possible_members[enabled] print(f"members selected: {len(members)}") # mirror the members to the right side members_mirror = np.copy(members) for member in members_mirror: for point in member: point[0] *= -1 point[0] += width * 2 members = np.append(members, members_mirror, axis=0) truss = SystemElements(EA=MODULUS_OF_ELASTICITY * BRASS_CROSS_SECTION_AREA, EI=MODULUS_OF_ELASTICITY * MOMENT_OF_INERTIA) for member in members: truss.add_truss_element(member) try: truss.add_support_hinged(node_id=truss.find_node_id(vertex=[0, 0])) truss.add_support_hinged(node_id=truss.find_node_id( vertex=[width * 2, 0])) return truss except: return None
def makestructure(nodes, segs, fixednodes, loadnodes, thicknesses, tensile=tensilePLA, totalload=100): ss = SystemElements() #loop through segments and create them for s, thickness in zip(segs, thicknesses): ss.add_truss_element(location=[nodes[s[0]], nodes[s[1]]], EA=tensile * thickness * strutwidth, g=0, spring={ 1: 0.0001, 2: 0.0001 }) # for f, supporttype in fixednodes: if supporttype == 'hinged': ss.add_support_hinged(node_id=f + 1) elif supporttype == 'roll': ss.add_support_roll(node_id=f + 1, direction='x') elif supporttype == 'fixed': ss.add_support_fixed(node_id=f + 1) #add in other types of supports here for l in loadnodes: ss.point_load(l + 1, Fx=0, Fy=-totalload / len(loadnodes)) return ss
#!/usr/bin/env python3 from anastruct import SystemElements import math width = 15 height = 4 ss = SystemElements(EA=15000, EI=5000) ss.add_truss_element(location=[[0, 0], [0, height]]) ss.add_truss_element(location=[[0, 0], [width, 0]]) ss.add_truss_element(location=[[0, 4], [width, height]]) ss.add_truss_element(location=[[width, height], [width, 0]]) ss.add_truss_element(location=[[0, height], [width/4, 0]]) ss.add_truss_element(location=[[width/4*2, height], [width/4, 0]]) ss.add_truss_element(location=[[width/4*2, height], [width/4*3, 0]]) ss.add_truss_element(location=[[width, height], [width/4*3, 0]]) ss.add_support_fixed(node_id=ss.find_node_id(vertex=[0, 0])) ss.add_support_fixed(node_id=ss.find_node_id(vertex=[15, 0])) ss.point_load(Fy=-300, node_id=ss.find_node_id(vertex=[width/2, height])) ss.solve() # Get visual results. ss.show_structure() # ss.show_reaction_force() # ss.show_axial_force() # ss.show_shear_force() # ss.show_bending_moment() # ss.show_displacement()
def generate_truss(subdivide_mode=None, subdivides=None): """ Randomly generate a valid truss """ ss = SystemElements(EA=MODULUS_OF_ELASTICITY * BRASS_CROSS_SECTION_AREA, EI=MODULUS_OF_ELASTICITY * MOMENT_OF_INERTIA) width = MIN_WIDTH height = MAX_HEIGHT if not subdivide_mode: subdivide_mode = random.choice( ["triangle_subdivide", "radial_subdivide", "pillar_subdivide"]) if subdivide_mode == "triangle_subdivide": if not subdivides: subdivides = random.randint(1, 2) triangles = [ [ [[0, 0], [width, 0]], [[width, 0], [width / 2, height]], [[width / 2, height], [0, 0]], ], ] for _ in range(subdivides): new_triangles = [] for triangle in triangles: mids = [midpoint(*line) for line in triangle] new_triangles += [ [ [triangle[0][0], mids[0]], [mids[0], mids[2]], [mids[2], triangle[0][0]], ], [ [mids[2], mids[1]], [mids[1], triangle[2][0]], [triangle[2][0], mids[2]], ], [ [mids[0], triangle[1][0]], [triangle[1][0], mids[1]], [mids[1], mids[0]], ], [ [mids[2], mids[0]], [mids[0], mids[1]], [mids[1], mids[2]], ], ] triangles = new_triangles raw_lines = np.reshape(triangles, (-1, 2, 2)) # sort coordinates in each line raw_lines = [sorted(line, key=lambda p: p[0]) for line in raw_lines] # sort lines by first point's x value raw_lines = sorted(raw_lines, key=lambda l: l[0][0]) # remove duplicate lines lines = [] for line in raw_lines: is_duplicate = False for l in lines: if np.array_equal(line, l): is_duplicate = True if not is_duplicate: lines.append(line) for line in lines: ss.add_truss_element(location=line) elif subdivide_mode == "radial_subdivide": if not subdivides: subdivides = random.randint(1, 4) step_size = width / 2 / subdivides bottom_midpoint = midpoint([0, 0], [width, 0]) lines = [] for x in np.arange(0, width + 0.1, step_size): lines += [ [ bottom_midpoint, [ x, valmap(x, 0, width / 2, 0, height) if x <= width / 2 else valmap(x, width / 2, width, height, 0) ] ], ] lines[-1][1][1] = 0 # HACK: set last y value to 0 top_points = [p[1] for p in lines] top_lines = [] for i in range(1, len(top_points)): top_lines += [[top_points[i - 1], top_points[i]]] lines += top_lines for line in lines: ss.add_truss_element(location=line) elif subdivide_mode == "pillar_subdivide": if not subdivides: subdivides = random.randint(1, 4) step_size = width / 2 / subdivides lines = [] for x in np.arange(step_size, width, step_size): lines += [ [[x, 0], [ x, valmap(x, 0, width / 2, 0, height) if x <= width / 2 else valmap(x, width / 2, width, height, 0) ]], ] top_points = [p[1] for p in lines] edge_lines = [] for i in range(1, len(top_points)): edge_lines += [ [top_points[i - 1], top_points[i]], [[top_points[i - 1][0], 0], [top_points[i][0], 0]], ] if i < len(top_points) / 2: edge_lines += [ [[top_points[i - 1][0], 0], top_points[i]], ] else: edge_lines += [ [top_points[i - 1], [top_points[i][0], 0]], ] lines += [ [[0, 0], top_points[0]], [[0, 0], [top_points[0][0], 0]], [[width, 0], top_points[-1]], [[width, 0], [top_points[-1][0], 0]], ] lines += edge_lines for line in lines: ss.add_truss_element(location=line) ss.add_support_hinged(node_id=ss.find_node_id(vertex=[0, 0])) ss.add_support_hinged(node_id=ss.find_node_id(vertex=[width, 0])) return ss
def accept(self): try: E = float(self.form.editE.text()) # N/mm2 I = float(self.form.editI.text()) # mm4 A = float(self.form.editA.text()) # mm2 ss = SystemElements() frame = FreeCAD.ActiveDocument.getObjectsByLabel( self.form.comboBox.currentText())[0] sk = frame.Base j = 0 # CREATE MEMBERS OF STRUCTURE for l in sk.Geometry: sp = [i * 1e-3 for i in list(l.StartPoint)[:2]] ep = [i * 1e-3 for i in list(l.EndPoint)[:2]] if self.combotypes[j].currentText() == 'beam': ss.add_element([sp, ep], EA=E * A * 1e-3, EI=E * I * 1e-9) elif self.combotypes[j].currentText() == 'brace': ss.add_truss_element([sp, ep], EA=E * A * 1e-3) j += 1 # SET DISTRIBUTED LOADS if self.form.radioFrame.isChecked(): for i in list(range(len(sk.Geometry))): if self.form.tableDistrib.item(i, 2): item = self.form.tableDistrib.item(i, 2) try: load = float(item.text()) # kN/m ss.q_load(element_id=(i + 1), q=load) except: pass for c in self.combos: i = self.combos.index(c) + 1 # SET NODE CONSTRAINTS if c.currentText() == 'fix': ss.add_support_fixed(node_id=i) elif c.currentText() == 'hinge': ss.add_support_hinged(node_id=i) elif c.currentText() == 'roll': ss.add_support_roll(node_id=i) # SET NODE FORCES if self.form.tableConc.item( i - 1, 1) or self.form.tableConc.item(i - 1, 2): itemX = self.form.tableConc.item(i - 1, 1) try: loadX = float(itemX.text()) # kN except: loadX = 0 itemY = self.form.tableConc.item(i - 1, 2) # kN try: loadY = float(itemY.text()) except: loadY = 0 ss.point_load(node_id=(i), Fx=loadX, Fy=loadY) # SOLVE AND VALIDATE ss.solve() # stable=ss.validate(.0000001) # SHOW RESULTS ACCORDING THE CALC TYPE if True: #stable: if self.form.radioFrame.isChecked(): ss.show_results() elif self.form.radioTruss.isChecked(): ss.show_axial_force() else: FreeCAD.Console.PrintError('The structure is not stable.\n') except: FreeCAD.Console.PrintError('Invalid input\n') for l in self.labNodes + self.labEl: l.removeLabel()
def trussbridge(Ediag, Adiag, Ebot, Abot, Etop, Atop, p, w_tri=4, h_tri=2, num_tri=6, disp=False): """ Calculate displacement of middle point in bridge truss Args: Ediag (list): list of Young's modulus for each pair of diagonal trusses (Pa) Adiag (list): list of cross-sectional area for each pair of diagonal trusses (m2) Ebot (list): list of Young's modulus for each bottom truss (Pa) Abot (list): list of cross-sectional area for each bottom truss (m2) Etop (list): list of Young's modulus for each top truss (Pa) Atop (list): list of cross-sectional area for each top truss (m2)t p (list): list of force applied on the top nodes (N) num_tri (int): number of triangles disp (bool): display image or not """ Ediag = np.array(Ediag) Adiag = np.array(Adiag) Ebot = np.array(Ebot) Abot = np.array(Abot) Etop = np.array(Etop) Atop = np.array(Atop) EAdiag = Ediag * Adiag EAbot = Ebot * Abot EAtop = Etop * Atop ss = SystemElements() # Triangle coord x_base = np.arange(0, num_tri + 1) * w_tri x_top = np.arange(0, num_tri) * w_tri + h_tri y = np.ones(num_tri) * h_tri # Create 6 triangles for i in range(num_tri): p1 = [x_base[i], 0] p2 = [x_top[i], y[i]] p3 = [x_base[i + 1], 0] ss.add_truss_element(location=[p1, p2], EA=EAdiag[i]) ss.add_truss_element(location=[p2, p3], EA=EAdiag[i]) ss.add_truss_element(location=[p1, p3], EA=EAbot[i]) # Create 5 horizontal trusses for i in range(num_tri - 1): ss.add_truss_element(location=[[x_top[i], y[i]], [x_top[i + 1], y[i + 1]]], EA=EAtop[i]) # Create support ss.add_support_hinged(node_id=1) ss.add_support_roll(node_id=13, direction=2) # Create Load loadnode = [2, 4, 6, 8, 12] for index, point in enumerate(loadnode): ss.point_load(node_id=point, Fy=p[index]) ss.point_load(node_id=point, Fy=p[index]) ss.point_load(node_id=point, Fy=p[index]) ss.point_load(node_id=point, Fy=p[index]) ss.solve() disp7 = ss.get_node_displacements(node_id=7) if disp is True: ss.show_axial_force() ss.show_displacement(factor=10) return disp7