mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
moving code to shape builder
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -20,195 +20,8 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
from math import cos, tan, pi
|
||||
from pathlib import Path
|
||||
from mathutils import Vector
|
||||
from itertools import chain
|
||||
|
||||
from ifcopenshell.util.shape_builder import ShapeBuilder
|
||||
|
||||
V = lambda *x: Vector([float(i) for i in x])
|
||||
|
||||
|
||||
def get_simple_2dcurve_data(coords, fillets=[], fillet_radius=[], closed=True, ifc_file=None):
|
||||
"""
|
||||
Creates simple 2D curve from set of 2d coords and list of points with fillets.
|
||||
Simple curve means that all fillets are based on 90 degree angle.
|
||||
|
||||
> coords: list of 2d coords. Example: ((x0,y0), (x1,y1), (x2, y2))
|
||||
> fillets: list of points from `coords` to base fillet on. Example: (1,)
|
||||
> fillet_radius: list of fillet radius for each of corresponding point form `fillets`. Example: (5.,)
|
||||
Note: filler_radius could be just 1 float value if it's the same for all fillets.
|
||||
|
||||
Optional arguments:
|
||||
> closed: boolean whether curve should be closed (whether last point connected to first one). Default: True
|
||||
> ifc_file: ifc file to create IfcIndexedPolyCurve for the function output
|
||||
|
||||
< returns (points, segments, ifc_curve) for the created simple curve
|
||||
if both points in e are equally far from pt, then v1 is returned."""
|
||||
|
||||
# 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([len(points) - 1, 0])
|
||||
|
||||
# replace negative index
|
||||
if segments[0][0] == -1:
|
||||
segments[0][0] = len(points) - 1
|
||||
|
||||
# sometime fillet points could match previous or next points in line
|
||||
# I remove them at the end to avoid making fillet algorithm even less readable
|
||||
points, segments = remove_redundant_points(points, segments)
|
||||
ifc_curve = None
|
||||
if ifc_file:
|
||||
ifc_points = ifc_file.createIfcCartesianPointList2D(points)
|
||||
ifc_segments = []
|
||||
for segment in segments:
|
||||
segment = [i + 1 for i in segment]
|
||||
if len(segment) == 2:
|
||||
ifc_segments.append(ifc_file.createIfcLineIndex(segment))
|
||||
elif len(segment) == 3:
|
||||
ifc_segments.append(ifc_file.createIfcArcIndex(segment))
|
||||
|
||||
ifc_curve = ifc_file.createIfcIndexedPolyCurve(Points=ifc_points, Segments=ifc_segments)
|
||||
return (points, segments, ifc_curve)
|
||||
|
||||
|
||||
def remove_redundant_points(points, segments):
|
||||
# prevent mutating
|
||||
points = [tuple(p) for p in points]
|
||||
segments = segments.copy()
|
||||
|
||||
# find duplicate points, reindex them in segments
|
||||
# and mark them to delete later
|
||||
points_to_remove = []
|
||||
prev_point = 0
|
||||
for i, p in enumerate(points[1:], 1):
|
||||
if p != points[prev_point]:
|
||||
prev_point = i
|
||||
continue
|
||||
|
||||
valid_segments = []
|
||||
for s in segments:
|
||||
s = [ps if ps != i else prev_point for ps in s]
|
||||
valid_segments.append(s)
|
||||
segments = valid_segments
|
||||
points_to_remove.append(i)
|
||||
|
||||
# remove duplicate segments
|
||||
valid_segments = [segment for segment in segments if len(set(segment)) != 1]
|
||||
points = [point for i, point in enumerate(points) if i not in points_to_remove]
|
||||
# correct the order in segments
|
||||
unique_points = sorted(set(chain(*valid_segments)))
|
||||
unique_points_translation = {prev: i for i, prev in enumerate(unique_points)}
|
||||
valid_segments = [[unique_points_translation[p] for p in s] for s in valid_segments]
|
||||
|
||||
return points, valid_segments
|
||||
|
||||
|
||||
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 = get_simple_2dcurve_data(
|
||||
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
|
||||
|
||||
|
||||
def create_transition_arc_ifc(width, height, ifc_file=None):
|
||||
# create an arc in the rectangle with specified width and height
|
||||
# if it's not possible to make a complete arc
|
||||
# it will create arc with longest radius possible
|
||||
# and straight segment in the middle
|
||||
fillet_size = (width / 2) / height
|
||||
if fillet_size <= 1:
|
||||
fillet_radius = height * fillet_size
|
||||
curve_coords = [
|
||||
(0.0, 0.0),
|
||||
(0.0, height),
|
||||
(width * 0.5, height),
|
||||
(width, height),
|
||||
(width, 0.0),
|
||||
]
|
||||
fillets = (1, 3)
|
||||
else:
|
||||
fillet_radius = height
|
||||
curve_coords = [
|
||||
(0.0, 0.0),
|
||||
(0.0, height),
|
||||
(fillet_radius, height),
|
||||
(width - fillet_radius, height),
|
||||
(width, height),
|
||||
(width, 0.0),
|
||||
]
|
||||
fillets = (1, 4)
|
||||
points, segments, transition_arc = get_simple_2dcurve_data(
|
||||
curve_coords, fillets, fillet_radius, closed=False, ifc_file=ifc_file
|
||||
)
|
||||
return points, segments, transition_arc
|
||||
from ifcopenshell.util.shape_builder import ShapeBuilder, V
|
||||
|
||||
|
||||
class LibraryGenerator:
|
||||
@@ -289,12 +102,12 @@ class LibraryGenerator:
|
||||
if position:
|
||||
kwargs["position"] = position
|
||||
|
||||
_, _, rectangle = get_simple_2dcurve_data(
|
||||
_, _, rectangle = builder.get_simple_2dcurve_data(
|
||||
coords=builder.get_rectangle_coords(**kwargs),
|
||||
fillets=(0, 1, 2, 3),
|
||||
fillet_radius=fillet_radius,
|
||||
closed=True,
|
||||
ifc_file=self.file,
|
||||
create_ifc_curve=True,
|
||||
)
|
||||
return rectangle
|
||||
|
||||
@@ -431,9 +244,9 @@ class LibraryGenerator:
|
||||
second_arc_depth = depth * (1 - 0.10)
|
||||
second_arc_width = width - (depth - second_arc_depth) * 2
|
||||
polyline = builder.polyline((V(0, 0), V(width, 0)))
|
||||
_, _, first_semicircle = create_transition_arc_ifc(width, depth, ifc_file=self.file)
|
||||
_, _, first_semicircle = builder.create_transition_arc_ifc(width, depth, create_ifc_curve=True)
|
||||
|
||||
_, _, second_semicircle = create_transition_arc_ifc(second_arc_width, second_arc_depth, ifc_file=self.file)
|
||||
_, _, second_semicircle = builder.create_transition_arc_ifc(second_arc_width, second_arc_depth, create_ifc_curve=True)
|
||||
builder.translate(second_semicircle, V((width - second_arc_width) / 2, 0))
|
||||
|
||||
builder.translate([polyline, first_semicircle, second_semicircle], shift_to_center)
|
||||
@@ -1105,8 +918,8 @@ class LibraryGenerator:
|
||||
fillets_radius = [fillets_radius * 5] * 2 + [fillets_radius] * 2
|
||||
else:
|
||||
fillets_radius = [fillets_radius] * 4
|
||||
_, _, fillet_rectangle = get_simple_2dcurve_data(
|
||||
coords=coords, fillets=(0, 1, 2, 3), fillet_radius=fillets_radius, closed=True, ifc_file=self.file
|
||||
_, _, fillet_rectangle = builder.get_simple_2dcurve_data(
|
||||
coords=coords, fillets=(0, 1, 2, 3), fillet_radius=fillets_radius, closed=True, create_ifc_curve=True
|
||||
)
|
||||
|
||||
circle_position = V(
|
||||
@@ -1182,8 +995,8 @@ class LibraryGenerator:
|
||||
]
|
||||
fillets = (0, 1, 6, 7)
|
||||
fillet_radius = (width / 2, width / 5, width / 5, width / 2)
|
||||
_, _, seat = get_simple_2dcurve_data(
|
||||
coords, fillets, fillet_radius=fillet_radius, closed=True, ifc_file=self.file
|
||||
_, _, seat = builder.get_simple_2dcurve_data(
|
||||
coords, fillets, fillet_radius=fillet_radius, closed=True, create_ifc_curve=True
|
||||
)
|
||||
seat_first_part = ifcopenshell.util.element.copy_deep(self.file, seat)
|
||||
|
||||
@@ -1251,8 +1064,8 @@ class LibraryGenerator:
|
||||
size=V(width, depth - cistern_depth), position=V(0, cistern_depth) + shift_to_center
|
||||
)
|
||||
fillet_radius = min(width / 2, (depth - cistern_depth) / 2)
|
||||
_, _, seat_main_curve = get_simple_2dcurve_data(
|
||||
seat_main_curve_points, fillets=(2, 3), fillet_radius=fillet_radius, closed=True, ifc_file=self.file
|
||||
_, _, seat_main_curve = builder.get_simple_2dcurve_data(
|
||||
seat_main_curve_points, fillets=(2, 3), fillet_radius=fillet_radius, closed=True, create_ifc_curve=True
|
||||
)
|
||||
seat_main_curve_mask = builder.circle(center=V(0, depth - fillet_radius), radius=fillet_radius * 0.75)
|
||||
seat_main_curve_profile = builder.profile(seat_main_curve, inner_curves=seat_main_curve_mask)
|
||||
|
||||
@@ -24,119 +24,8 @@ import ifcopenshell.api
|
||||
import boltspy as bolts
|
||||
from math import cos, pi
|
||||
from pathlib import Path
|
||||
from mathutils import Vector
|
||||
from ifcopenshell.util.shape_builder import ShapeBuilder, V
|
||||
|
||||
V = lambda *x: Vector([float(i) for i in x])
|
||||
|
||||
def create_simple_2dcurve(coords, fillets, fillet_radius, closed=True, ifc_file=None):
|
||||
"""
|
||||
Creates simple 2D curve from set of 2d coords and list of points with fillets.
|
||||
Simple curve means that all fillets are based on 90 degree angle.
|
||||
|
||||
> coords: list of 2d coords. Example: ((x0,y0), (x1,y1), (x2, y2))
|
||||
> fillets: list of points from `coords` to base fillet on. Example: (1,)
|
||||
> fillet_radius: list of fillet radius for each of corresponding point form `fillets`. Example: (5.,)
|
||||
Note: filler_radius could be just 1 float value if it's the same for all fillets.
|
||||
|
||||
Optional arguments:
|
||||
> closed: boolean whether curve should be closed (whether last point connected to first one). Default: True
|
||||
> ifc_file: ifc file to create IfcIndexedPolyCurve for the function output
|
||||
|
||||
< returns (points, segments, ifc_curve) for the created simple curve
|
||||
if both points in e are equally far from pt, then v1 is returned."""
|
||||
|
||||
# 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_segments = []
|
||||
for segment in segments:
|
||||
segment = [i+1 for i in segment]
|
||||
if len(segment) == 2:
|
||||
ifc_segments.append( ifc_file.createIfcLineIndex( segment ))
|
||||
elif len(segment) == 3:
|
||||
ifc_segments.append( ifc_file.createIfcArcIndex( segment ))
|
||||
|
||||
ifc_curve = ifc_file.createIfcIndexedPolyCurve(Points=ifc_points, Segments=ifc_segments)
|
||||
|
||||
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_2dcurve(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"):
|
||||
@@ -158,6 +47,7 @@ class LibraryGenerator:
|
||||
)
|
||||
dim_exponents = self.file.createIfcDimensionalExponents(0, 0, 0, 0, 0, 0, 0)
|
||||
length_unit = ifcopenshell.api.run("unit.add_si_unit", self.file, unit_type="LENGTHUNIT", prefix="MILLI")
|
||||
builder = ShapeBuilder(self.file)
|
||||
|
||||
# define angle unit to use degrees for IfcPlaneAngleMeasure:
|
||||
# https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcPlaneAngleMeasure.htm
|
||||
@@ -258,7 +148,7 @@ class LibraryGenerator:
|
||||
# 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_curve = builder.create_z_profile_lips_curve(**ifc_params)
|
||||
ifc_params = {"OuterCurve": ifc_curve}
|
||||
elif prof_type == "profile_l*lbeam_2l":
|
||||
profiles_gap = ifc_params["ProfilesGap"]
|
||||
|
||||
@@ -21,6 +21,7 @@ import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
from math import cos, sin, pi
|
||||
from mathutils import Vector, Matrix
|
||||
from itertools import chain
|
||||
|
||||
V = lambda *x: Vector([float(i) for i in x])
|
||||
sign = lambda x: x and (1, -1)[x < 0]
|
||||
@@ -635,3 +636,182 @@ class ShapeBuilder:
|
||||
elif polyline.is_a("IfcPolyline"):
|
||||
for i, co in enumerate(coords):
|
||||
polyline.Points[i].Coordinates = co
|
||||
|
||||
def get_simple_2dcurve_data(self, coords, fillets=[], fillet_radius=[], closed=True, create_ifc_curve=None):
|
||||
"""
|
||||
Creates simple 2D curve from set of 2d coords and list of points with fillets.
|
||||
Simple curve means that all fillets are based on 90 degree angle.
|
||||
|
||||
> coords: list of 2d coords. Example: ((x0,y0), (x1,y1), (x2, y2))
|
||||
> fillets: list of points from `coords` to base fillet on. Example: (1,)
|
||||
> fillet_radius: list of fillet radius for each of corresponding point form `fillets`. Example: (5.,)
|
||||
Note: filler_radius could be just 1 float value if it's the same for all fillets.
|
||||
|
||||
Optional arguments:
|
||||
> closed: boolean whether curve should be closed (whether last point connected to first one). Default: True
|
||||
> create_ifc_curve: create IfcIndexedPolyCurve or just return the data. Default: False
|
||||
|
||||
< returns (points, segments, ifc_curve) for the created simple curve
|
||||
if both points in e are equally far from pt, then v1 is returned."""
|
||||
|
||||
def remove_redundant_points(points, segments):
|
||||
# prevent mutating
|
||||
points = [tuple(p) for p in points]
|
||||
segments = segments.copy()
|
||||
|
||||
# find duplicate points, reindex them in segments
|
||||
# and mark them to delete later
|
||||
points_to_remove = []
|
||||
prev_point = 0
|
||||
for i, p in enumerate(points[1:], 1):
|
||||
if p != points[prev_point]:
|
||||
prev_point = i
|
||||
continue
|
||||
|
||||
valid_segments = []
|
||||
for s in segments:
|
||||
s = [ps if ps != i else prev_point for ps in s]
|
||||
valid_segments.append(s)
|
||||
segments = valid_segments
|
||||
points_to_remove.append(i)
|
||||
|
||||
# remove duplicate segments
|
||||
valid_segments = [segment for segment in segments if len(set(segment)) != 1]
|
||||
points = [point for i, point in enumerate(points) if i not in points_to_remove]
|
||||
# correct the order in segments
|
||||
unique_points = sorted(set(chain(*valid_segments)))
|
||||
unique_points_translation = {prev: i for i, prev in enumerate(unique_points)}
|
||||
valid_segments = [[unique_points_translation[p] for p in s] for s in valid_segments]
|
||||
|
||||
return points, valid_segments
|
||||
|
||||
# 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([len(points) - 1, 0])
|
||||
|
||||
# replace negative index
|
||||
if segments[0][0] == -1:
|
||||
segments[0][0] = len(points) - 1
|
||||
|
||||
# sometime fillet points could match previous or next points in line
|
||||
# I remove them at the end to avoid making fillet algorithm even less readable
|
||||
points, segments = remove_redundant_points(points, segments)
|
||||
ifc_curve = None
|
||||
if create_ifc_curve:
|
||||
ifc_points = self.file.createIfcCartesianPointList2D(points)
|
||||
ifc_segments = []
|
||||
for segment in segments:
|
||||
segment = [i + 1 for i in segment]
|
||||
if len(segment) == 2:
|
||||
ifc_segments.append(self.file.createIfcLineIndex(segment))
|
||||
elif len(segment) == 3:
|
||||
ifc_segments.append(self.file.createIfcArcIndex(segment))
|
||||
|
||||
ifc_curve = self.file.createIfcIndexedPolyCurve(Points=ifc_points, Segments=ifc_segments)
|
||||
return (points, segments, ifc_curve)
|
||||
|
||||
def create_z_profile_lips_curve(self, FirstFlangeWidth, SecondFlangeWidth, Depth, Girth, WallThickness, FilletRadius):
|
||||
x1 = FirstFlangeWidth
|
||||
x2 = SecondFlangeWidth
|
||||
y = Depth / 2
|
||||
g = Girth
|
||||
t = WallThickness
|
||||
r = FilletRadius
|
||||
|
||||
# fmt: off
|
||||
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)
|
||||
)
|
||||
# fmt: on
|
||||
|
||||
# option for no additional thickness in outer radius:
|
||||
# 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 = self.get_simple_2dcurve_data(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, create_ifc_curve=True)
|
||||
|
||||
return ifc_curve
|
||||
|
||||
def create_transition_arc_ifc(self, width, height, create_ifc_curve=False):
|
||||
# create an arc in the rectangle with specified width and height
|
||||
# if it's not possible to make a complete arc
|
||||
# it will create arc with longest radius possible
|
||||
# and straight segment in the middle
|
||||
fillet_size = (width / 2) / height
|
||||
if fillet_size <= 1:
|
||||
fillet_radius = height * fillet_size
|
||||
curve_coords = [
|
||||
(0.0, 0.0),
|
||||
(0.0, height),
|
||||
(width * 0.5, height),
|
||||
(width, height),
|
||||
(width, 0.0),
|
||||
]
|
||||
fillets = (1, 3)
|
||||
else:
|
||||
fillet_radius = height
|
||||
curve_coords = [
|
||||
(0.0, 0.0),
|
||||
(0.0, height),
|
||||
(fillet_radius, height),
|
||||
(width - fillet_radius, height),
|
||||
(width, height),
|
||||
(width, 0.0),
|
||||
]
|
||||
fillets = (1, 4)
|
||||
points, segments, transition_arc = self.get_simple_2dcurve_data(
|
||||
curve_coords, fillets, fillet_radius, closed=False, create_ifc_curve=create_ifc_curve
|
||||
)
|
||||
return points, segments, transition_arc
|
||||
Reference in New Issue
Block a user