Added c-, z-profiles with lips to AU steel library

Added c- and z-profiles with lips to IFC AU Steel profile library (based on data from https://github.com/boltsparts/boltsparts/pull/15).

For z-profiles I've created simple 2D curve generation function that can be reused later - it requires list of points and list of points with fillets and the results are list of curve points, segments and IfcIndexedPolyCurve.

Example:

    points, segments, ifc_curve = create_simple_curve_from_coords(coords,
        fillets =     (0,   1,   4, 5, 6,   7,   10, 11),
        fillet_radius=(r+t, r+t, r, r, r+t, r+t, r, r),
        closed=True, ifc_file=ifc_file)
This commit is contained in:
Andrej730
2022-11-15 13:35:44 +06:00
parent 308ee7f7a9
commit ff2714d991
3 changed files with 9007 additions and 8431 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -22,7 +22,105 @@
import ifcopenshell
import ifcopenshell.api
import boltspy as bolts
from math import cos, pi
# TODO: move to some utils module?
# simple curve means that all filles are based on 90 degree angle
# output: (2dpoints, segments, ifc_curve if ifc_file is supplied)
def create_simple_curve_from_coords(coords, fillets, fillet_radius, closed=True, ifc_file=None):
# option to use same fillet radius for all fillets
if isinstance(fillet_radius, float):
fillet_radius = [fillet_radius] * len(fillets)
fillets = dict(zip(fillets, fillet_radius))
segments = []
points = []
for co_i, co in enumerate(coords, 0):
current_point = len(points)
if co_i in fillets:
r = fillets[co_i]
rsb = r * cos(pi/4) # radius shift big
rss = r - rsb # radius shift small
next_co = coords[(co_i+1) % len(coords)]
previous_co = coords[co_i-1]
# identify fillet type (1 of 4 possible types)
x_direction = 1 if coords[co_i][0] < previous_co[0] or coords[co_i][0] < next_co[0] else -1
y_direction = 1 if coords[co_i][1] < previous_co[1] or coords[co_i][1] < next_co[1] else -1
xshift_point = (co[0] + r * x_direction, co[1])
middle_point = (co[0] + rss * x_direction, co[1] + rss * y_direction)
yshift_point = (co[0], co[1] + r * y_direction)
# identify fillet direction
if co[1] == previous_co[1]:
points.extend( (xshift_point, middle_point, yshift_point))
else:
points.extend( (yshift_point, middle_point, xshift_point))
segments.append( [current_point-1, current_point] )
segments.append( [current_point, current_point+1, current_point+2] )
else:
points.append( co )
if co_i != 0:
segments.append( [current_point-1, current_point] )
if closed:
segments.append( [0, len(points)-1] )
# replace negative index
if segments[0][0] == -1:
segments[0][0] = len(points) - 1
ifc_curve = None
if ifc_file:
ifc_points = ifc_file.createIfcCartesianPointList2D(points)
ifc_segements = []
for segment in segments:
segment = [i+1 for i in segment]
if len(segment) == 2:
ifc_segements.append( ifc_file.createIfcLineIndex( segment ))
elif len(segment) == 3:
ifc_segements.append( ifc_file.createIfcArcIndex( segment ))
ifc_curve = ifc_file.createIfcIndexedPolyCurve(Points=ifc_points, Segments=ifc_segements)
return (points, segments, ifc_curve)
def create_z_profile_lips_curve(ifc_file, FirstFlangeWidth, SecondFlangeWidth, Depth, Girth, WallThickness, FilletRadius):
x1 = FirstFlangeWidth
x2 = SecondFlangeWidth
y = Depth / 2
g = Girth
t = WallThickness
r = FilletRadius
coords = (
(-t/2, y),
(x2, y),
(x2, y-g),
(x2-t, y-g),
(x2-t, y-t),
(t/2, y-t),
(t/2, -y),
(-x1, -y),
(-x1, -y+g),
(-x1+t, -y+g),
(-x1+t, -y+t),
(-t/2, -y+t)
)
# no additional thickness in outer radius option
# points, segments, ifc_curve = create_curve_from_coords(coords, fillets = (0, 1, 4, 5, 6, 7, 10, 11), fillet_radius=r, closed=True, ifc_file=ifc_file)
points, segments, ifc_curve = create_simple_curve_from_coords(coords,
fillets = (0, 1, 4, 5, 6, 7, 10, 11),
fillet_radius=(r+t, r+t, r, r, r+t, r+t, r, r),
closed=True, ifc_file=ifc_file)
return ifc_curve
class LibraryGenerator:
def generate(self, parse_profiles_type="EU", output_filename="IFC4 EU Steel.ifc"):
@@ -77,6 +175,8 @@ class LibraryGenerator:
"profile_hollow*_circle": ("IfcCircleHollowProfileDef", {"t": "WallThickness", "D": "Radius"}),
"profile_hollow*_square": ("IfcRectangleHollowProfileDef", {"t": "WallThickness", "b": "XDim", "ri": "InnerFilletRadius", "ro": "OuterFilletRadius"}),
"profile_hollow*_rectangular": ("IfcRectangleHollowProfileDef", {"t": "WallThickness", "b": "XDim", "h": "YDim", "ri": "InnerFilletRadius", "ro": "OuterFilletRadius"}),
"profile_c_lips": ("IfcCShapeProfileDef", {"t": "WallThickness", "b": "Width", "h": "Depth", "ll": "Girth", "r": "InternalFilletRadius"}),
"profile_z_lips": ("IfcArbitraryClosedProfileDef", {"t": "WallThickness", "c1": "FirstFlangeWidth", "c2": "SecondFlangeWidth", "h": "Depth", "r": "FilletRadius", "ll": "Girth"}),
}
if parse_profiles_type == "AU":
@@ -117,6 +217,9 @@ class LibraryGenerator:
elif prof_type == "profile_hollow*_circle":
# by default bolts provides diameter, so we need to convert it to radius
ifc_params["Radius"] /= 2
elif prof_type == "profile_z_lips":
ifc_curve = create_z_profile_lips_curve(self.file, **ifc_params)
ifc_params = {"OuterCurve": ifc_curve}
# profile is setup by type of profile and by supplying it's parameters
# ProfileType stays AREA
@@ -199,6 +302,3 @@ class LibraryGenerator:
if __name__ == "__main__":
LibraryGenerator().generate(parse_profiles_type="EU", output_filename="..\\blenderbim\\bim\\data\\libraries\\IFC4 EU Steel.ifc")
LibraryGenerator().generate(parse_profiles_type="AU", output_filename="..\\blenderbim\\bim\\data\\libraries\\IFC4 AU Steel.ifc")
# C:\Projects\GitHub\IfcOpenShell\src\blenderbim\scripts\generate_steel_profiles_library.py
# C:\Projects\GitHub\IfcOpenShell\src\blenderbimIFC4 AU Steel.ifc