Created
March 14, 2026 23:26
-
-
Save edp8489/d125f4b709f2b8e253e19bce2082613f to your computer and use it in GitHub Desktop.
sectionproperties: angled hat section
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from sectionproperties.pre.geometry import Geometry | |
| from sectionproperties.pre.pre import Material, DEFAULT_MATERIAL | |
| from sectionproperties.pre.library.primitive_sections import rectangular_section | |
| from math import radians, sin, cos | |
| def angled_hat( | |
| dim_1: float, | |
| dim_2: float, | |
| dim_3: float, | |
| dim_4: float, | |
| dim_5: float, | |
| dim_6: float, | |
| dim_7: float = None, | |
| material: Material = DEFAULT_MATERIAL, | |
| ) -> Geometry: | |
| """ | |
| Creates a hat section with angled walls and | |
| dim_1: total height (Y) | |
| dim_2: brim width | |
| dim_3: cap width | |
| dim_4: web thickness | |
| dim_5: cap thickness | |
| dim_6: web angle in degrees, 0 is vertical, 90 is horizontal | |
| dim_7: skin thickness (to close section for torsion constant calculation) | |
| """ | |
| overall_height = dim_1 | |
| brim_width = dim_2 | |
| cap_width = dim_3 | |
| web_thickness = dim_4 | |
| cap_thickness = dim_5 | |
| web_angle_deg = dim_6 | |
| web_angle_rad = radians(web_angle_deg) | |
| # TODO Better validation and throw error instead | |
| if web_angle_deg < 0 or web_angle_deg >= 90: | |
| print(f"ERROR: Web angle ({web_angle_deg}) out of bounds. Value must be in range [0,90) degrees.") | |
| return | |
| # define exterior points from left to right, stopping at midplane | |
| pt_a0_l_bot = (0, 0) | |
| pt_a0_l_top = (0, web_thickness) | |
| pt_a0_r_bot = (brim_width + web_thickness, 0) | |
| pt_a0_r_top = (brim_width, web_thickness) | |
| h2 = overall_height - cap_thickness | |
| h_sl = (overall_height - cap_thickness / 2 - web_thickness / 2) / cos(web_angle_rad) | |
| l_sl = h_sl * sin(web_angle_rad) | |
| l2 = brim_width + l_sl | |
| pt_a1_r_bot = (l2 + web_thickness, h2) | |
| pt_a1_r_top = (l2, overall_height) | |
| midplane_width = l2 + (cap_width / 2) | |
| pt_a2_mid_bot = (midplane_width, h2) | |
| pt_a2_mid_top = (midplane_width, overall_height) | |
| points = [ | |
| pt_a0_l_bot, | |
| pt_a0_r_bot, | |
| pt_a1_r_bot, | |
| pt_a2_mid_bot, | |
| pt_a2_mid_top, | |
| pt_a1_r_top, | |
| pt_a0_r_top, | |
| pt_a0_l_top, | |
| ] | |
| facets = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 0)] | |
| # Create half the shape then mirror about the midplane | |
| shape_L = Geometry.from_points( | |
| points=points, | |
| facets=facets, | |
| control_points=[(brim_width / 2, web_thickness / 2)], | |
| material=material | |
| ) | |
| shape_R = shape_L.mirror_section(axis="y", mirror_point=(midplane_width, 0)) | |
| angled_hat = shape_L + shape_R | |
| # TODO refactor into separate `angled_hat_with_skin()` constructor | |
| if dim_7 is not None: | |
| t_skin = dim_7 | |
| bounding_box = angled_hat.calculate_extents() | |
| overall_width = bounding_box[1] - bounding_box[0] | |
| skin = rectangular_section(d=t_skin, b=overall_width).align_to( | |
| other=angled_hat, on="bottom" | |
| ) | |
| angled_hat += skin | |
| else: | |
| print( | |
| "WARN: dim_7 (skin thickness) not provided. Shape is open and warping properties cannot be calculated." | |
| ) | |
| return angled_hat |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment