Files
IfcOpenShell/src/blenderbim/scripts/generate_furniture_library.py
T
Andrej730 47f57d20cd Fixed couple bugs in furniture library
1) last polyline point was failing on Consecutive rule causing validation errors
2) Fixed wrong ifc class for dishwasher (was used occurence class instead of type)
2023-04-21 18:24:32 +05:00

2068 lines
95 KiB
Python

# BlenderBIM Add-on - OpenBIM Blender Add-on
# Copyright (C) 2022 @Andrej730
#
# This file is part of BlenderBIM Add-on.
#
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BlenderBIM Add-on is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
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
class LibraryGenerator:
def generate(self, output_filename="IFC4 EU Steel.ifc"):
ifcopenshell.api.pre_listeners = {}
ifcopenshell.api.post_listeners = {}
self.materials = {}
self.file = ifcopenshell.api.run("project.create_file")
self.project = ifcopenshell.api.run(
"root.create_entity", self.file, ifc_class="IfcProject", name=f"Non-structural assets library"
)
self.library = ifcopenshell.api.run(
"root.create_entity", self.file, ifc_class="IfcProjectLibrary", name=f"Non-structural assets library"
)
ifcopenshell.api.run(
"project.assign_declaration", self.file, definition=self.library, relating_context=self.project
)
unit = ifcopenshell.api.run("unit.add_si_unit", self.file, unit_type="LENGTHUNIT", prefix="MILLI")
ifcopenshell.api.run("unit.assign_unit", self.file, units=[unit])
model = ifcopenshell.api.run("context.add_context", self.file, context_type="Model")
plan = ifcopenshell.api.run("context.add_context", self.file, context_type="Plan")
self.representations = {
"model_body": ifcopenshell.api.run(
"context.add_context",
self.file,
context_type="Model",
context_identifier="Body",
target_view="MODEL_VIEW",
parent=model,
),
"plan_body": ifcopenshell.api.run(
"context.add_context",
self.file,
context_type="Plan",
context_identifier="Body",
target_view="PLAN_VIEW",
parent=plan,
),
}
builder = ShapeBuilder(self.file)
def create_box_objects(width, depth, height, shift_to_center=False, return_representations=False):
output = []
rectangle = builder.rectangle(size=V(width, depth))
box = builder.extrude(builder.profile(rectangle), height)
if return_representations:
representation_3d = builder.get_representation(context=self.representations["model_body"], items=box)
output.append(representation_3d)
else:
output.append([box])
rectangle = builder.rectangle(size=V(width, depth))
if return_representations:
representation_2d = builder.get_representation(self.representations["plan_body"], rectangle)
output.append(representation_2d)
else:
output.append([rectangle])
if shift_to_center:
shift_to_center = V(-width / 2, -depth / 2)
builder.translate(output[0], shift_to_center.to_3d())
builder.translate(output[1], shift_to_center)
return output
def create_fillet_rectangle(size=None, position=None, fillet_radius=50.0):
"""`fillet_radius` is either float or list of floats for each corner
in counter-clockwise order starting from bottom left"""
kwargs = dict()
if size:
kwargs["size"] = size
if position:
kwargs["position"] = position
_, _, rectangle = 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,
)
return rectangle
# beds
representation_3d, representation_2d = create_box_objects(680.0, 1300.0, 550.0, return_representations=True)
self.create_explicit_type("IfcFurnitureType", "Cot mattress", representation_3d, representation_2d)
def create_fancy_bed_representations(overall_width, overall_depth, overall_height, blanket_tan=tan(pi / 8)):
# 0.85h - blanket starts
# 0.7w - blanket shifts
# 0.25h - blanket shift ends
# o.2w - pillow starts
bed = builder.rectangle(size=V(overall_width, overall_depth))
blanket_pillow = builder.polyline(
(
[0.0, overall_depth * 0.85],
# pillow
[overall_width * 0.2, overall_depth * 0.85],
[overall_width * 0.2, overall_depth],
[overall_width * 0.2, overall_depth * 0.85],
[overall_width * 0.7, overall_depth * 0.85],
# pillow
[overall_width * 0.8, overall_depth * 0.85 - overall_width * (0.8 - 0.7) * blanket_tan],
[overall_width * 0.8, overall_depth],
[overall_width * 0.8, overall_depth * 0.85 - overall_width * (0.8 - 0.7) * blanket_tan],
[overall_width, overall_depth * 0.85 - overall_width * (1 - 0.7) * blanket_tan],
)
)
representation_2d = builder.get_representation(self.representations["plan_body"], [bed, blanket_pillow])
curve = builder.rectangle(size=V(overall_width, overall_depth))
mesh = builder.extrude(builder.profile(curve), overall_height)
representation_3d = builder.get_representation(context=self.representations["model_body"], items=mesh)
return representation_3d, representation_2d
representation_3d, representation_2d = create_fancy_bed_representations(920.0, 1880.0, 550.0)
self.create_explicit_type("IfcFurnitureType", "Single bed", representation_3d, representation_2d)
representation_3d, representation_2d = create_fancy_bed_representations(920.0, 2030.0, 550.0)
self.create_explicit_type("IfcFurnitureType", "Long single bed", representation_3d, representation_2d)
representation_3d, representation_2d = create_fancy_bed_representations(1070.0, 2030.0, 550.0)
self.create_explicit_type("IfcFurnitureType", "King single bed", representation_3d, representation_2d)
representation_3d, representation_2d = create_fancy_bed_representations(1380.0, 1880.0, 550.0)
self.create_explicit_type("IfcFurnitureType", "Double bed", representation_3d, representation_2d)
representation_3d, representation_2d = create_fancy_bed_representations(1530.0, 2030.0, 550.0)
self.create_explicit_type("IfcFurnitureType", "Queen bed", representation_3d, representation_2d)
representation_3d, representation_2d = create_fancy_bed_representations(1830.0, 2030.0, 550.0)
self.create_explicit_type("IfcFurnitureType", "King bed", representation_3d, representation_2d)
representation_3d, representation_2d = create_fancy_bed_representations(2030.0, 2030.0, 550.0)
self.create_explicit_type("IfcFurnitureType", "Super King bed", representation_3d, representation_2d)
# wardrobes
def create_fancy_wardrobe_representations(overall_width, overall_depth, overall_height):
curve = builder.rectangle(size=V(overall_width, overall_depth))
mesh = builder.extrude(builder.profile(curve), overall_height)
representation_3d = builder.get_representation(context=self.representations["model_body"], items=mesh)
rect = builder.rectangle(size=V(overall_width, overall_depth))
cloth = []
# 1 cloth every 200 mm
# cloth step = 200m
# cloth height offset = 0.1h
# cloth width offset = 0.5step
cloths_amount = int(overall_width) // 200 + ((int(overall_width) % 200) > 200 * (0.5 + 0.1 + 0.05))
for i in range(cloths_amount):
tilt_offset = 0 if i % 2 == 0 else 200 * 0.2
c = builder.polyline(
[
(i * 200 + 200 * 0.5 - tilt_offset, 0.1 * overall_depth),
(i * 200 + 200 * 0.5 + tilt_offset, (1 - 0.1) * overall_depth),
]
)
cloth.append(c)
representation_2d = builder.get_representation(self.representations["plan_body"], items=[rect, *cloth])
return representation_3d, representation_2d
representation_3d, representation_2d = create_fancy_wardrobe_representations(1800.0, 600.0, 2100.0)
self.create_explicit_type("IfcFurnitureType", "ADG Main Bedroom Wardrobe", representation_3d, representation_2d)
representation_3d, representation_2d = create_fancy_wardrobe_representations(1000.0, 600.0, 2500.0)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Single Person Wardrobe", representation_3d, representation_2d
)
# chairs
def create_fancy_chair(width, depth, height, seat_level, return_representations=False):
thickness = 50.0
shift_to_center = V(-width / 2, 0)
mirror_axis = V(0, 1)
output = []
items_to_adjust = []
items_3d = []
chair_back = None
items_to_adjust.append(seat := builder.rectangle(size=V(width, depth)))
leg = builder.rectangle(size=V(thickness, thickness))
legs = [leg] + builder.mirror(
leg, mirror_axes=[V(1, 0), V(0, 1), V(1, 1)], mirror_point=V(width / 2, depth / 2), create_copy=True
)
items_to_adjust.extend(legs)
if height > seat_level:
items_to_adjust.append(chair_back := builder.rectangle(size=V(width, thickness)))
builder.translate(items_to_adjust, shift_to_center)
builder.mirror(items_to_adjust, mirror_axis)
items_3d.append(
builder.extrude(
builder.profile(seat), thickness, position=V(0, 0, seat_level), extrusion_vector=V(0, 0, -1)
)
)
if chair_back:
items_3d.append(
builder.extrude(
builder.profile(chair_back),
height - seat_level,
position=V(0, 0, height),
extrusion_vector=V(0, 0, -1),
)
)
items_3d.extend([builder.extrude(leg, seat_level - thickness) for leg in legs])
if return_representations:
representation_3d = builder.get_representation(
context=self.representations["model_body"], items=items_3d
)
output.append(representation_3d)
else:
output.append(items_3d)
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)
_, _, second_semicircle = create_transition_arc_ifc(second_arc_width, second_arc_depth, ifc_file=self.file)
builder.translate(second_semicircle, V((width - second_arc_width) / 2, 0))
builder.translate([polyline, first_semicircle, second_semicircle], shift_to_center)
builder.translate([polyline, first_semicircle, second_semicircle], V(0, -depth))
items_2d = [polyline, first_semicircle, second_semicircle]
if return_representations:
representation_2d = builder.get_representation(self.representations["plan_body"], items_2d)
output.append(representation_2d)
else:
output.append(items_2d)
return output
representation_3d, representation_2d = create_fancy_chair(600.0, 400.0, 900.0, 450.0, True)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail Dining Chair", representation_3d, representation_2d
)
representation_3d, representation_2d = create_fancy_chair(300.0, 300.0, 800.0, 800.0, True)
self.create_explicit_type("IfcFurnitureType", "Neufert Retail Bar Stool", representation_3d, representation_2d)
# table
representation_3d, representation_2d = create_box_objects(
700.0, 500.0, 550.0, shift_to_center=True, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic Large Bedside Table", representation_3d, representation_2d
)
representation_3d, representation_2d = create_box_objects(
600.0, 450.0, 550.0, shift_to_center=True, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic Medium Bedside Table", representation_3d, representation_2d
)
representation_3d, representation_2d = create_box_objects(
500.0, 380.0, 500.0, shift_to_center=True, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic Small Bedside Table", representation_3d, representation_2d
)
def create_fancy_rectangle_table(width, depth, height, return_representations=False):
output = []
leg_size = 50.0
countertop_thickness = 50.0
shift_to_center = V(-width / 2, -depth / 2)
rectangle = builder.rectangle(size=V(width, depth))
countertop = builder.extrude(
builder.profile(rectangle), countertop_thickness, V(0, 0, height - countertop_thickness)
)
leg_curve = builder.rectangle(size=V(leg_size, leg_size))
legs_curves = [leg_curve] + builder.mirror(
leg_curve,
mirror_axes=[V(1, 0), V(0, 1), V(1, 1)],
mirror_point=V(width / 2, depth / 2),
create_copy=True,
)
legs_profiles = [builder.profile(leg) for leg in legs_curves]
legs = [builder.extrude(leg, height - countertop_thickness) for leg in legs_profiles]
items = [countertop] + legs
builder.translate(items, shift_to_center.to_3d())
if return_representations:
representation_3d = builder.get_representation(context=self.representations["model_body"], items=items)
output.append(representation_3d)
else:
output.append(items)
rectangle = builder.rectangle(position=shift_to_center, size=V(width, depth))
if return_representations:
representation_2d = builder.get_representation(self.representations["plan_body"], rectangle)
output.append(representation_2d)
else:
output.append([rectangle])
return output
representation_3d, representation_2d = create_fancy_rectangle_table(750.0, 750.0, 450.0, True)
self.create_explicit_type(
"IfcFurnitureType", "Generic Medium Coffee Table", representation_3d, representation_2d
)
# tables
def create_rectangle_table_with_chairs(
table_width,
table_depth,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats,
side_seats=False,
):
items_table_3d, items_table_2d = create_fancy_rectangle_table(table_width, table_depth, table_height)
items_chair_3d, items_chair_2d = create_fancy_chair(chair_width, chair_depth, chair_height, seat_level)
if side_seats:
number_of_seats -= 2
seats_per_side = number_of_seats // 2
per_chair_gap = (table_width - chair_width * seats_per_side) / (seats_per_side + 1)
# 3d representation
items_chairs_3d = []
if side_seats:
items_chair_3d_transformed = builder.rotate(items_chair_3d, angle=90, create_copy=True)
builder.translate(items_chair_3d_transformed, V(table_width / 2 + table_chair_gap + chair_depth, 0, 0))
items_chairs_3d.append(items_chair_3d_transformed)
items_chairs_3d.append(
builder.mirror(items_chair_3d_transformed, mirror_axes=V(1, 0), create_copy=True)
)
# create_copy condiition is needed to avoid having one unused chair in ifc
for i in range(seats_per_side):
coords = V(
-table_width / 2 + per_chair_gap + i * (chair_width + per_chair_gap) + chair_width / 2,
table_depth / 2 + table_chair_gap + chair_depth,
0,
)
cur_items_chair_3d = builder.translate(items_chair_3d, coords, create_copy=i != seats_per_side - 1)
items_chairs_3d.append(cur_items_chair_3d)
items_chairs_3d.append(builder.mirror(cur_items_chair_3d, mirror_axes=V(0, 1), create_copy=True))
items_chairs_3d = list(chain(*items_chairs_3d))
representation_3d = builder.get_representation(
self.representations["model_body"], items=items_table_3d + items_chairs_3d
)
# 2d representation
items_chairs_2d = []
if side_seats:
items_chair_2d_transformed = builder.rotate(items_chair_2d, angle=90, create_copy=True)
builder.translate(items_chair_2d_transformed, V(table_width / 2 + table_chair_gap + chair_depth, 0))
items_chairs_2d.append(items_chair_2d_transformed)
items_chairs_2d.append(
builder.mirror(items_chair_2d_transformed, mirror_axes=V(1, 0), create_copy=True)
)
# create_copy condiition is needed to avoid having one unused chair in ifc
for i in range(seats_per_side):
coords = V(
-table_width / 2 + per_chair_gap + i * (chair_width + per_chair_gap) + chair_width / 2,
table_depth / 2 + table_chair_gap + chair_depth,
)
cur_items_chair_2d = builder.translate(items_chair_2d, coords, create_copy=i != seats_per_side - 1)
items_chairs_2d.append(cur_items_chair_2d)
items_chairs_2d.append(builder.mirror(cur_items_chair_2d, mirror_axes=V(0, 1), create_copy=True))
items_chairs_2d = list(chain(*items_chairs_2d))
representation_2d = builder.get_representation(
self.representations["plan_body"], items=items_table_2d + items_chairs_2d
)
return representation_3d, representation_2d
# short 4-seater table
overall_width, overall_depth, overall_height = (1750.0, 1750.0, 900.0)
table_width, table_depth, table_height = (850.0, 850.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_rectangle_table_with_chairs(
table_width,
table_depth,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=4,
side_seats=True,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 4-Seater Square Table", representation_3d, representation_2d
)
# wide 4-seater table
overall_width, overall_depth, overall_height = (1300.0, 2000.0, 900.0)
table_width, table_depth, table_height = (1300.0, 800.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (450.0, 450.0, 900.0, 450.0)
representation_3d, representation_2d = create_rectangle_table_with_chairs(
table_width,
table_depth,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=4,
side_seats=False,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Residential 4-Seater Rectangular Table", representation_3d, representation_2d
)
# 2-seater table
overall_width, overall_depth, overall_height = (625.0, 1750.0, 900.0)
table_width, table_depth, table_height = (625.0, 800.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_rectangle_table_with_chairs(
table_width,
table_depth,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=2,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 2-Seater Rectangular Table", representation_3d, representation_2d
)
# 4-seater table
overall_width, overall_depth, overall_height = (1250.0, 1750.0, 900.0)
table_width, table_depth, table_height = (1250.0, 800.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_rectangle_table_with_chairs(
table_width,
table_depth,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=4,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 4-Seater Rectangular Table", representation_3d, representation_2d
)
# 6-seater table
overall_width, overall_depth, overall_height = (1875.0, 1750.0, 900.0)
table_width, table_depth, table_height = (1875.0, 800.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_rectangle_table_with_chairs(
table_width,
table_depth,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=6,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 6-Seater Rectangular Table", representation_3d, representation_2d
)
# 8-seater table
overall_width, overall_depth, overall_height = (2500.0, 1750.0, 900.0)
table_width, table_depth, table_height = (2500.0, 800.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_rectangle_table_with_chairs(
table_width,
table_depth,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=8,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 8-Seater Rectangular Table", representation_3d, representation_2d
)
# 12-seater table
overall_width, overall_depth, overall_height = (3750.0, 1750.0, 900.0)
table_width, table_depth, table_height = (3750.0, 800.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_rectangle_table_with_chairs(
table_width,
table_depth,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=12,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 12-Seater Rectangular Table", representation_3d, representation_2d
)
def create_fancy_circular_table(diameter, height, return_representations=False):
radius = diameter / 2
width, depth = radius, radius
output = []
leg_size = 50.0
countertop_thickness = 50.0
shift_to_center = V(-width / 2, -depth / 2)
circle = builder.circle(radius=radius)
countertop = builder.extrude(
builder.profile(circle), countertop_thickness, V(0, 0, height - countertop_thickness)
)
leg_curve = builder.circle(radius=leg_size)
leg = builder.extrude(builder.profile(leg_curve), height - countertop_thickness)
items = [countertop, leg]
if return_representations:
representation_3d = builder.get_representation(context=self.representations["model_body"], items=items)
output.append(representation_3d)
else:
output.append(items)
circle = builder.circle(radius=radius)
if return_representations:
representation_2d = builder.get_representation(self.representations["plan_body"], circle)
output.append(representation_2d)
else:
output.append([circle])
return output
def create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats,
side_seats=False,
):
items_table_3d, items_table_2d = create_fancy_circular_table(table_diameter, table_height)
items_chair_3d, items_chair_2d = create_fancy_chair(chair_width, chair_depth, chair_height, seat_level)
per_chair_angle = 360 / number_of_seats
table_radius = table_diameter / 2
# 3d rerpresentation
items_chairs_3d = []
# create_copy condiition is needed to avoid having one unused chair in ifc
for i in range(number_of_seats):
last_seat = i == number_of_seats - 1
cur_items_chair_3d = builder.translate(
items_chair_3d, V(0, table_radius + table_chair_gap + chair_depth, 0), create_copy=not last_seat
)
builder.rotate(cur_items_chair_3d, per_chair_angle * i)
items_chairs_3d.append(cur_items_chair_3d)
items_chairs_3d = list(chain(*items_chairs_3d))
representation_3d = builder.get_representation(
self.representations["model_body"], items=items_table_3d + items_chairs_3d
)
# 2d representation
items_chairs_2d = []
# create_copy condiition is needed to avoid having one unused chair in ifc
for i in range(number_of_seats):
last_seat = i == number_of_seats - 1
cur_items_chair_2d = builder.translate(
items_chair_2d, V(0, table_radius + table_chair_gap + chair_depth), create_copy=not last_seat
)
builder.rotate(cur_items_chair_2d, per_chair_angle * i)
items_chairs_2d.append(cur_items_chair_2d)
items_chairs_2d = list(chain(*items_chairs_2d))
representation_2d = builder.get_representation(
self.representations["plan_body"], items=items_table_2d + items_chairs_2d
)
return representation_3d, representation_2d
# circular 2-seater table
overall_width, overall_depth, overall_height = (1500.0, 1500.0, 900.0)
table_diameter, table_height = (600.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=2,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 2-Seater Circular Table", representation_3d, representation_2d
)
# circular 3-seater table
overall_width, overall_depth, overall_height = (1700.0, 1700.0, 900.0)
table_diameter, table_height = (800.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=3,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 3-Seater Circular Table", representation_3d, representation_2d
)
# circular 4-seater table
overall_width, overall_depth, overall_height = (1800.0, 1800.0, 900.0)
table_diameter, table_height = (900.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=4,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 4-Seater Circular Table", representation_3d, representation_2d
)
# circular 5-seater table
overall_width, overall_depth, overall_height = (2000.0, 2000.0, 900.0)
table_diameter, table_height = (1100.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=5,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 5-Seater Circular Table", representation_3d, representation_2d
)
# circular 6-seater table
overall_width, overall_depth, overall_height = (2150.0, 2150.0, 900.0)
table_diameter, table_height = (1250.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=6,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 6-Seater Circular Table", representation_3d, representation_2d
)
# circular 8-seater table
overall_width, overall_depth, overall_height = (2300.0, 2300.0, 900.0)
table_diameter, table_height = (1400.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=8,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 8-Seater Circular Table", representation_3d, representation_2d
)
# circular 10-seater table
overall_width, overall_depth, overall_height = (2450.0, 2450.0, 900.0)
table_diameter, table_height = (1550.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=10,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 10-Seater Circular Table", representation_3d, representation_2d
)
# circular 12-seater table
overall_width, overall_depth, overall_height = (2750.0, 2750.0, 900.0)
table_diameter, table_height = (1850.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=12,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 12-Seater Circular Table", representation_3d, representation_2d
)
# circular 14-seater table
overall_width, overall_depth, overall_height = (3100.0, 3100.0, 900.0)
table_diameter, table_height = (2200.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=14,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 14-Seater Circular Table", representation_3d, representation_2d
)
# circular 16-seater table
overall_width, overall_depth, overall_height = (3400.0, 3400.0, 900.0)
table_diameter, table_height = (2500.0, 780.0)
table_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_circular_table_with_chairs(
table_diameter,
table_height,
chair_width,
chair_depth,
chair_height,
seat_level,
table_chair_gap,
number_of_seats=16,
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Retail 16-Seater Circular Table", representation_3d, representation_2d
)
# sofas
def create_sofa(width, depth, height, seat_level, number_of_seats=1):
thickness = 175
armrest_height = height * 0.7
shift_to_center = V(-width / 2, -depth)
mirror_axis = V(0, 1)
seat_width = (width - thickness * 2) / number_of_seats
# 3d representation
armrest = builder.rectangle(size=V(thickness, depth))
armrest = builder.extrude(armrest, armrest_height)
armrests = [armrest, builder.translate(armrest, V(width - thickness, 0, 0), create_copy=True)]
seats = []
for i in range(number_of_seats):
seat = builder.rectangle(
size=V(seat_width, depth - thickness), position=V(thickness + seat_width * i, 0)
)
seat = builder.extrude(seat, seat_level)
seats.append(seat)
seat_back = builder.rectangle(
size=V(width - thickness * 2, thickness), position=V(thickness, depth - thickness)
)
seat_back = builder.extrude(seat_back, height)
items = armrests + seats + [seat_back]
builder.translate(items, shift_to_center.to_3d())
# builder.mirror(items, mirror_axis)
representation_3d = builder.get_representation(self.representations["model_body"], items=items)
# 2d representation
armrest = builder.rectangle(size=V(thickness, depth))
armrests = [armrest, builder.translate(armrest, V(width - thickness, 0), create_copy=True)]
seats = []
for i in range(number_of_seats):
seat = builder.rectangle(
size=V(seat_width, depth - thickness), position=V(thickness + seat_width * i, 0)
)
seats.append(seat)
seat_back = builder.rectangle(
size=V(width - thickness * 2, thickness), position=V(thickness, depth - thickness)
)
items = armrests + seats + [seat_back]
builder.translate(items, shift_to_center)
representation_2d = builder.get_representation(self.representations["plan_body"], items=items)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height, seat_level = (900.0, 900.0, 900.0, 450.0)
representation_3d, representation_2d = create_sofa(overall_width, overall_depth, overall_height, seat_level)
self.create_explicit_type("IfcFurnitureType", "Generic 1-Seater Sofa", representation_3d, representation_2d)
overall_width, overall_depth, overall_height, seat_level, number_of_seats = (1500.0, 900.0, 900.0, 450.0, 2)
representation_3d, representation_2d = create_sofa(
overall_width, overall_depth, overall_height, seat_level, number_of_seats
)
self.create_explicit_type("IfcFurnitureType", "Generic 2-Seater Sofa", representation_3d, representation_2d)
overall_width, overall_depth, overall_height, seat_level, number_of_seats = (2100.0, 900.0, 900.0, 450.0, 3)
representation_3d, representation_2d = create_sofa(
overall_width, overall_depth, overall_height, seat_level, number_of_seats
)
self.create_explicit_type("IfcFurnitureType", "Generic 3-Seater Sofa", representation_3d, representation_2d)
# showers
def create_shower_or_bathtube(width, depth, height, bathtube=False):
items_box, items_rectangle = create_box_objects(width, depth, height)
rect_offset = 50.0
fillets_radius = 50.0
sink_radius = 25.0
coords = [
(rect_offset, rect_offset),
(rect_offset, depth - rect_offset),
(width - rect_offset, depth - rect_offset),
(width - rect_offset, rect_offset),
]
if bathtube:
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
)
circle_position = V(
width - rect_offset * 2 - sink_radius,
(depth - rect_offset * 2 - sink_radius) if not bathtube else depth / 2,
)
sink_circle = builder.circle(circle_position, radius=sink_radius)
items_2d = items_rectangle + [fillet_rectangle, sink_circle]
representation_2d = builder.get_representation(self.representations["plan_body"], items=items_2d)
representation_3d = builder.get_representation(self.representations["model_body"], items=items_box)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height = (900.0, 750.0, 2100.0)
representation_3d, representation_2d = create_shower_or_bathtube(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Shower 75x90", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (800.0, 800.0, 2100.0)
representation_3d, representation_2d = create_shower_or_bathtube(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Shower 80x80", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (900.0, 900.0, 2100.0)
representation_3d, representation_2d = create_shower_or_bathtube(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Shower 90x90", representation_3d, representation_2d)
# bathtubs
overall_width, overall_depth, overall_height = (1600.0, 700.0, 550.0)
representation_3d, representation_2d = create_shower_or_bathtube(
overall_width, overall_depth, overall_height, bathtube=True
)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Small Bathtub", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (1700.0, 750.0, 550.0)
representation_3d, representation_2d = create_shower_or_bathtube(
overall_width, overall_depth, overall_height, bathtube=True
)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Medium Bathtub", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (1800.0, 800.0, 550.0)
representation_3d, representation_2d = create_shower_or_bathtube(
overall_width, overall_depth, overall_height, bathtube=True
)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Large Bathtub", representation_3d, representation_2d)
def create_toilet(width, depth, height, seat_level=0):
shift_to_center = V(-width / 2, 0)
mirror_axis = V(0, 1)
cistern_used = not bool(seat_level)
if cistern_used:
cistern_height = 0
cistern_depth = 0
seat_level = height
else:
cistern_height = height - seat_level
cistern_depth = 200.0
# 2d representation
depth_offset = depth * 0.1
width_offset = width * 0.1
items_2d = []
items_2d_to_mirror = []
coords = [
(0.0, 0.0),
(0.0, depth - depth_offset - cistern_depth),
(width_offset, depth - depth_offset - cistern_depth),
(width_offset, depth - cistern_depth),
(width - width_offset, depth - cistern_depth),
(width - width_offset, depth - depth_offset - cistern_depth),
(width, depth - depth_offset - cistern_depth),
(width, 0.0),
]
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_first_part = ifcopenshell.util.element.copy_deep(self.file, seat)
seat_depth_offset = (depth - cistern_depth) * 0.3
seat_width_offset = 0.7 * width / 2 if cistern_depth else width / 2
seat_start_width_offset = 0.6 * width
if cistern_height:
cistern = builder.rectangle(size=V(width, cistern_depth), position=shift_to_center)
cistern_3d = ifcopenshell.util.element.copy_deep(self.file, cistern)
items_2d_to_mirror.append(cistern)
else:
back_wall_polyline = builder.polyline(
((-seat_start_width_offset / 2, 0.0), (seat_start_width_offset / 2, 0.0))
)
items_2d.append(back_wall_polyline)
# seat
seat_polyline = builder.polyline(
((seat_start_width_offset / 2, 0.0), (seat_width_offset, seat_depth_offset)),
position_offset=V(0, cistern_depth),
)
seat_curve = builder.create_ellipse_curve(
seat_width_offset, depth - seat_depth_offset - cistern_depth, trim_points_mask=(0, 2)
)
builder.translate(seat_curve, V(0, cistern_depth + seat_depth_offset))
items_2d_to_mirror.extend([seat_polyline, seat_curve])
items_2d_to_mirror.append(builder.mirror(seat_polyline, mirror_axes=V(1, 0), create_copy=True))
# seat_second_line
second_line_height = (depth - cistern_depth) * 0.7
second_line_width = (width - cistern_depth) * 0.75
second_curve_y = cistern_depth + second_line_height / 2 * 1.6
seat_second_curve = builder.create_ellipse_curve(second_line_width / 2, second_line_height / 2)
builder.translate(seat_second_curve, V(0, second_curve_y))
items_2d_to_mirror.append(seat_second_curve)
# bowl
bowl_width = width / 2 * 0.25
bowl_depth = (depth - cistern_depth) * 0.1
bowl_points = (
(-bowl_width / 2, 0.0),
(-bowl_width / 2, -bowl_depth / 2),
(bowl_width / 2, -bowl_depth / 2),
(bowl_width / 2, 0.0),
)
bowl_polyline = builder.polyline(bowl_points)
bowl_curve = builder.create_ellipse_curve(bowl_width / 2, bowl_depth / 2, trim_points_mask=(0, 2))
builder.translate([bowl_polyline, bowl_curve], V(0, second_curve_y))
items_2d_to_mirror.extend([bowl_polyline, bowl_curve])
builder.mirror(items_2d_to_mirror, mirror_axes=mirror_axis)
items_2d += items_2d_to_mirror
representation_2d = builder.get_representation(context=self.representations["plan_body"], items=items_2d)
# 3d representation
items_3d = []
items_3d_to_mirror = []
# seat
seat_main_curve_points = builder.get_rectangle_coords(
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_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)
seat_level_offset = seat_level / 2 / 4
seat_first_part = builder.extrude(
seat_main_curve_profile, seat_level / 2 - seat_level_offset, V(0, 0, seat_level / 2 + seat_level_offset)
)
seat_main_curve = ifcopenshell.util.element.copy_deep(self.file, seat_main_curve)
seat_second_part = builder.extrude(seat_main_curve, seat_level_offset, V(0, 0, seat_level / 2))
items_3d_to_mirror.extend([seat_first_part, seat_second_part])
seat_leg = builder.rectangle(size=V(width, depth / 3), position=V(0, depth / 3) + shift_to_center)
seat_leg = builder.extrude(seat_leg, seat_level / 2)
items_3d_to_mirror.append(seat_leg)
# cistern
if cistern_height:
cistern_3d = builder.extrude(
cistern_3d, cistern_height + seat_level / 2, position=V(0, 0, seat_level / 2)
)
items_3d_to_mirror.append(cistern_3d)
builder.translate(items_3d, shift_to_center.to_3d())
builder.mirror(items_3d_to_mirror, mirror_axes=mirror_axis)
items_3d += items_3d_to_mirror
representation_3d = builder.get_representation(context=self.representations["model_body"], items=items_3d)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height, seat_level = (550.0, 650.0, 770.0, 400)
representation_3d, representation_2d = create_toilet(overall_width, overall_depth, overall_height, seat_level)
self.create_explicit_type(
"IfcSanitaryTerminalType", "Neufert Toilet with Cistern", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (400.0, 530.0, 400.0)
representation_3d, representation_2d = create_toilet(overall_width, overall_depth, overall_height)
self.create_explicit_type(
"IfcSanitaryTerminalType", "Generic Toilet without Cistern", representation_3d, representation_2d
)
def create_urinal(width, depth, height):
shift_to_center = V(-width / 2, 0)
mirror_axis = V(0, 1)
back_wall_depth = depth * 0.1
back_wall_border_mask_height = height * 0.1
back_wall_border_mask_depth = depth * 0.1
back_wall_border_mask_width = width * 0.2
bottom_height = back_wall_border_mask_height / 2
bottom_mask_depth = depth * 0.1
bottom_mask_width = width * 0.2
bottom_mask_height = height * 0.2
items_3d_to_center = []
# back wall
back_wall = builder.rectangle(V(width, height))
# example of rotating and extruding by Y axis btw
back_wall_extruded = builder.extrude(
back_wall,
back_wall_depth + back_wall_border_mask_depth,
position_z_axis=V(0, -1, 0),
extrusion_vector=V(0, 0, -1),
)
items_3d_to_center.append(back_wall_extruded)
# bottom part
base_curve = builder.create_ellipse_curve(
width / 2, depth - (back_wall_depth + bottom_mask_depth), trim_points_mask=(0, 2)
)
builder.translate(base_curve, V(0, back_wall_depth + bottom_mask_depth))
triangle_bottom_extruded = builder.extrude(base_curve, bottom_height)
second_curve = builder.create_ellipse_curve(
(width - bottom_mask_width) / 2,
depth - (back_wall_depth + bottom_mask_depth) - bottom_mask_depth,
trim_points_mask=(0, 2),
)
builder.translate(second_curve, V(0, back_wall_depth + bottom_mask_depth))
base_curve = ifcopenshell.util.element.copy_deep(self.file, base_curve)
mask_curve_profile = builder.profile(base_curve, inner_curves=second_curve)
triangle_bottom_wall_mask = builder.extrude(
mask_curve_profile, bottom_mask_height, position=V(0, 0, bottom_height)
)
builder.translate(items_3d_to_center, shift_to_center.to_3d())
items_3d = items_3d_to_center + [triangle_bottom_extruded, triangle_bottom_wall_mask]
builder.mirror(items_3d, mirror_axis)
representation_3d = builder.get_representation(self.representations["model_body"], items_3d)
# 2d representation
curve_offset_depth = depth * 0.1
curve_offset_width = width * 0.2
items_2d = []
trim_points = builder.get_trim_points_from_mask(width / 2, 0.0, (0, 2))
base_curve = builder.create_ellipse_curve(
width / 2, depth, trim_points=((width / 2, 0.0), (-width / 2, 0.0))
)
items_2d.append(base_curve)
items_2d.append(builder.polyline(trim_points))
items_2d.append(builder.circle(radius=back_wall_depth * 0.5, center=V(0, back_wall_depth * 2.5)))
second_curve = builder.create_ellipse_curve(
(width - bottom_mask_width) / 2,
depth - (back_wall_depth + bottom_mask_depth) - bottom_mask_depth,
trim_points_mask=(0, 2),
)
builder.translate(second_curve, V(0, 2 * curve_offset_depth))
items_2d.append(second_curve)
curve_coords = builder.get_trim_points_from_mask(curve_offset_width / 2, curve_offset_depth, (3, 2))
second_curve = builder.curve_between_two_points(curve_coords)
builder.translate(second_curve, V(-width / 2 + curve_offset_width, 2 * curve_offset_depth))
polyline = builder.polyline(
((-width / 2 + curve_offset_width, 0.0), (width / 2 - curve_offset_width, 0.0)),
position_offset=V(0, curve_offset_depth),
)
items_2d.extend([second_curve, polyline])
items_2d.append(builder.mirror(second_curve, V(1, 0), create_copy=True))
builder.mirror(items_2d, mirror_axis)
representation_2d = builder.get_representation(self.representations["plan_body"], items_2d)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height = (350.0, 350.0, 650.0)
representation_3d, representation_2d = create_urinal(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Small Urinal", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (400.0, 400.0, 650.0)
representation_3d, representation_2d = create_urinal(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Medium Urinal", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (450.0, 450.0, 650.0)
representation_3d, representation_2d = create_urinal(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Large Urinal", representation_3d, representation_2d)
def create_basin(width, depth, height):
second_width = 0.9 * width
second_depth = 0.7 * depth
faucet_depth = depth - (depth - second_depth) / 2 / 2
faucet_length = 120.0
shift_to_center = V(-width / 2, -depth)
# representation 2d
rectangle_main = create_fillet_rectangle(size=V(width, depth))
rectangle_main_3d = ifcopenshell.util.element.copy_deep(self.file, rectangle_main)
rectangle_second = create_fillet_rectangle(
size=V(second_width, second_depth),
position=V((width - second_width) / 2, (depth - second_depth) * 0.3),
fillet_radius=(150.0, 150.0, 50.0, 50.0),
)
rectangle_second_3d = ifcopenshell.util.element.copy_deep(self.file, rectangle_second)
faucet = builder.polyline(((width / 2, faucet_depth), (width / 2, faucet_depth - faucet_length)))
items_2d = [rectangle_main, rectangle_second, faucet]
builder.translate(items_2d, shift_to_center)
representation_2d = builder.get_representation(self.representations["plan_body"], items_2d)
# representation 3d
basin_downside_thickness = 100.0
rectangle_profile = builder.profile(rectangle_main_3d, inner_curves=rectangle_second_3d)
main_basin = builder.extrude(
rectangle_profile, height - basin_downside_thickness, position=V(0, 0, basin_downside_thickness)
)
basin_downside = builder.extrude(rectangle_second_3d, basin_downside_thickness)
items_3d = [main_basin, basin_downside]
builder.translate(items_3d, shift_to_center.to_3d())
representation_3d = builder.get_representation(self.representations["model_body"], items_3d)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height = (450.0, 400.0, 250.0)
representation_3d, representation_2d = create_basin(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Extra Small Basin", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (500.0, 450.0, 250.0)
representation_3d, representation_2d = create_basin(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Small Basin", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (550.0, 500.0, 250.0)
representation_3d, representation_2d = create_basin(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Medium Basin", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (600.0, 550.0, 250.0)
representation_3d, representation_2d = create_basin(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcSanitaryTerminalType", "Neufert Large Basin", representation_3d, representation_2d)
def create_desk(width, depth, height, return_representations=False):
leg_width = 50.0
countertop_height = 50.0
backside_offset = 50.0
back_side_height = 0.6 * height
output = []
# 3d representation
items_3d = []
leg = builder.rectangle(size=V(leg_width, depth))
leg = builder.extrude(leg, height - countertop_height)
items_3d.append(leg)
items_3d.append(builder.translate(leg, V(width - leg_width, 0, 0), create_copy=True))
countertop = builder.rectangle(size=V(width, depth))
countertop = builder.extrude(countertop, countertop_height, V(0, 0, height - countertop_height))
items_3d.append(countertop)
backside = builder.rectangle(
size=V(width - leg_width * 2, backside_offset),
position=V(backside_offset, height - backside_offset * 4),
)
backside = builder.extrude(
backside, back_side_height, position=V(0, 0, height - back_side_height - backside_offset)
)
items_3d.append(backside)
if return_representations:
representation_3d = builder.get_representation(self.representations["model_body"], items_3d)
output.append(representation_3d)
else:
output.append(items_3d)
# 2d representation
rectangle = builder.rectangle(V(width, depth))
if return_representations:
representation_2d = builder.get_representation(self.representations["plan_body"], rectangle)
output.append(representation_2d)
else:
output.append([rectangle])
return output
overall_width, overall_depth, overall_height = (1560.0, 780.0, 780.0)
representation_3d, representation_2d = create_desk(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Commercial Writing Desk", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (1400.0, 700.0, 760.0)
representation_3d, representation_2d = create_desk(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Commercial Office Desk", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (1000.0, 600.0, 730.0)
representation_3d, representation_2d = create_desk(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type("IfcFurnitureType", "Generic Small Desk", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (1200.0, 700.0, 750.0)
representation_3d, representation_2d = create_desk(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type("IfcFurnitureType", "Generic Medium Desk", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (1500.0, 800.0, 750.0)
representation_3d, representation_2d = create_desk(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type("IfcFurnitureType", "Generic Large Desk", representation_3d, representation_2d)
def create_desk_with_chair(
desk_width, desk_depth, desk_height, chair_width, chair_depth, chair_height, seat_level, desk_chair_gap
):
desk_items_3d, desk_items_2d = create_desk(desk_width, desk_depth, desk_height)
chair_items_3d, chair_items_2d = create_fancy_chair(chair_width, chair_depth, chair_height, seat_level)
# 2d representation
builder.translate(desk_items_2d, V(0, chair_depth + desk_chair_gap))
builder.translate(chair_items_2d, V(desk_width / 2, 0))
builder.mirror(chair_items_2d, mirror_axes=V(0, 1))
items_2d = desk_items_2d + chair_items_2d
# 3d representation
builder.translate(desk_items_3d, V(0, chair_depth + desk_chair_gap, 0))
builder.translate(chair_items_3d, V(desk_width / 2, 0, 0))
builder.mirror(chair_items_3d, mirror_axes=V(0, 1))
items_3d = desk_items_3d + chair_items_3d
representation_3d = builder.get_representation(self.representations["model_body"], items_3d)
representation_2d = builder.get_representation(self.representations["plan_body"], items_2d)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height = (
1560.0,
1630.0,
900.0,
)
desk_width, desk_depth, desk_height = (
1560.0,
780.0,
780.0,
)
desk_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_desk_with_chair(
desk_width, desk_depth, desk_height, chair_width, chair_depth, chair_height, seat_level, desk_chair_gap
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Commercial Writing Desk and Chair", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (1400.0, 1450.0, 900.0)
desk_width, desk_depth, desk_height = (
1400.0,
700.0,
760.0,
)
desk_chair_gap = 50.0
chair_width, chair_depth, chair_height, seat_level = (400.0, 400.0, 900.0, 450.0)
representation_3d, representation_2d = create_desk_with_chair(
desk_width, desk_depth, desk_height, chair_width, chair_depth, chair_height, seat_level, desk_chair_gap
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Commercial Office Desk and Chair", representation_3d, representation_2d
)
def create_dishwasher(width, depth, height):
items_3d, items_2d = create_box_objects(width, depth, height)
circle_first_r = width * 0.1
circle_second_r = width * 0.3
center = V(width / 2, depth / 2)
k = center.y / center.x
circle_first = builder.circle(center=center, radius=circle_second_r)
circle_second = builder.circle(center=center, radius=circle_first_r)
polyline = builder.polyline([(0.0, 0.0), center - center.normalized() * circle_second_r])
mirrored_polylines = builder.mirror(
polyline, mirror_axes=[V(1, 0), V(0, 1), V(1, 1)], mirror_point=center, create_copy=True
)
items_2d.extend([circle_first, circle_second, polyline] + mirrored_polylines)
representation_3d = builder.get_representation(self.representations["model_body"], items_3d)
representation_2d = builder.get_representation(self.representations["plan_body"], items_2d)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height = (500.0, 570.0, 820.0)
representation_3d, representation_2d = create_dishwasher(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcElectricApplianceType", "Neufert Dishwasher", representation_3d, representation_2d)
def create_cooktop(width, depth, height):
items_3d, items_2d = create_box_objects(width, depth, height)
ring_radius = width * 0.1
ring_offset = V(width * 0.2, depth * 0.2)
center = V(width / 2, depth / 2)
ring = builder.circle(ring_offset, ring_radius)
mirrored_rings = builder.mirror(
ring, mirror_axes=[V(1, 0), V(0, 1), V(1, 1)], mirror_point=center, create_copy=True
)
items_2d.extend([ring] + mirrored_rings)
representation_3d = builder.get_representation(self.representations["model_body"], items_3d)
representation_2d = builder.get_representation(self.representations["plan_body"], items_2d)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height = (580.0, 510.0, 50.0)
representation_3d, representation_2d = create_cooktop(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcElectricApplianceType", "Neufert Cooktop 58x51", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (750.0, 510.0, 50.0)
representation_3d, representation_2d = create_cooktop(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcElectricApplianceType", "Neufert Cooktop 75x51", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (890.0, 510.0, 50.0)
representation_3d, representation_2d = create_cooktop(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcElectricApplianceType", "Neufert Cooktop 89x51", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (1750.0, 600.0, 850.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Small Kitchen Bench", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (1950.0, 600.0, 850.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Medium Kitchen Bench", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (2200.0, 600.0, 850.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Large Kitchen Bench", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (450.0, 400.0, 2030.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Small Full Height Cupboard", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (550.0, 500.0, 2030.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Medium Full Height Cupboard", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (600.0, 600.0, 2030.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Neufert Large Full Height Cupboard", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (600.0, 700.0, 900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic Kitchen Floor Module", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (600.0, 600.0, 2400.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic Full Height Cupboard", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (750.0, 650.0, 1900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type("IfcElectricApplianceType", "Generic Small Fridge Zone", representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (900.0, 700.0, 1900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcElectricApplianceType", "Generic Medium Fridge Zone", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (1000.0, 750.0, 1900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type("IfcElectricApplianceType", "Generic Large Fridge Zone", representation_3d, representation_2d)
def create_sink(width, depth, height, add_table):
shift_to_center = V(-width / 2, -depth)
rect_offset = 50.0
sink_offset = V(width / 2, 0) if add_table else V(0, 0)
# 2d representation
main_rectangle = builder.rectangle(size=V(width, depth))
sink_radius = 25.0
faucet_depth = depth - rect_offset / 4
faucet_length = 120.0
fillet_rectangle = create_fillet_rectangle(
size=V(width - rect_offset, depth - rect_offset) - sink_offset,
position=V(rect_offset / 2, rect_offset / 2) + sink_offset,
)
circle_position = sink_offset + V((width - sink_offset.x) / 2, depth - rect_offset * 2 - sink_radius)
sink_circle = builder.circle(circle_position, radius=sink_radius)
faucet = builder.polyline(
(
((width - sink_offset.x) / 2, faucet_depth),
((width - sink_offset.x) / 2, faucet_depth - faucet_length),
)
)
builder.translate(faucet, sink_offset)
items_2d = [main_rectangle, fillet_rectangle, sink_circle, faucet]
builder.translate(items_2d, shift_to_center)
# 3d representation
items_3d = []
sink_height = 0.8 * height
if add_table:
table = builder.rectangle(size=V(width, depth) - sink_offset)
table = builder.extrude(table, height)
items_3d.append(table)
sink_table = builder.rectangle(size=V(width, depth) - sink_offset, position=sink_offset)
sink_mask = create_fillet_rectangle(
size=V(width - rect_offset, depth - rect_offset) - sink_offset,
position=V(rect_offset / 2, rect_offset / 2) + sink_offset,
)
sink_profile = builder.profile(sink_table, inner_curves=sink_mask)
sink_table_extruded = builder.extrude(sink_profile, sink_height, position=V(0, 0, height - sink_height))
items_3d.append(sink_table_extruded)
sink_table_bottom = builder.extrude(sink_table, height - sink_height)
items_3d.append(sink_table_bottom)
builder.translate(items_3d, shift_to_center.to_3d())
representation_2d = builder.get_representation(self.representations["plan_body"], items=items_2d)
representation_3d = builder.get_representation(self.representations["model_body"], items=items_3d)
return representation_3d, representation_2d
sinks_data = {
"Neufert Sink 86x44": (860, 440, 180, False),
"Neufert Sink 110x44": (1110, 440, 180, True),
"Neufert Sink 124x44": (1240, 440, 180, True),
"Generic Small Sink": (450, 460, 210, False),
"Generic Medium Sink": (800, 460, 210, True),
"Generic Large Sink": (1100, 490, 220, True),
}
for sink_name in sinks_data:
parameters = [float(i) for i in sinks_data[sink_name][:3]]
add_table = sinks_data[sink_name][3]
overall_width, overall_depth, overall_height = parameters
representation_3d, representation_2d = create_sink(overall_width, overall_depth, overall_height, add_table)
self.create_explicit_type("IfcSanitaryTerminalType", sink_name, representation_3d, representation_2d)
overall_width, overall_depth, overall_height = (2200.0, 600.0, 900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic 1-Bedroom Island Bench", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (2400.0, 700.0, 900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic 2-Bedroom Island Bench", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (3000.0, 700.0, 900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic 3-Bedroom Island Bench", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (400.0, 500.0, 900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic Small Laundry Tub With Cupboard", representation_3d, representation_2d
)
overall_width, overall_depth, overall_height = (600.0, 500.0, 900.0)
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcFurnitureType", "Generic Medium Laundry Tub With Cupboard", representation_3d, representation_2d
)
def create_washing_machine(width, depth, height):
items_3d, items_2d = create_box_objects(width, depth, height)
circle_first_r = width * 0.1
circle_second_r = width * 0.3
center = V(width / 2, depth / 2)
circle_first = builder.circle(center=center, radius=circle_second_r)
circle_second = builder.circle(center=center, radius=circle_first_r)
items_2d.extend([circle_first, circle_second])
representation_3d = builder.get_representation(self.representations["model_body"], items_3d)
representation_2d = builder.get_representation(self.representations["plan_body"], items_2d)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height = (595.0, 680.0, 850.0)
representation_3d, representation_2d = create_washing_machine(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcElectricApplianceType", "Neufert Washing Machine", representation_3d, representation_2d)
def create_dryer_machine(width, depth, height):
items_3d, items_2d = create_box_objects(width, depth, height)
circle_first_r = width * 0.1
circle_second_r = width * 0.25
center_second_circle = V(width / 2, height - circle_second_r * 2.5)
circle_first = builder.circle(center=V(width / 2, circle_first_r * 1.5), radius=circle_first_r)
circle_second = builder.circle(center=center_second_circle, radius=circle_second_r)
polyline = builder.polyline(
[
V(-circle_second_r * 0.6, -((circle_second_r**2 - (circle_second_r * 0.6) ** 2) ** 0.5))
+ center_second_circle,
V(-circle_second_r * 0.1, (circle_second_r**2 - (circle_second_r * 0.1) ** 2) ** 0.5)
+ center_second_circle,
]
)
mirrored_polyline = builder.mirror(
polyline, mirror_point=center_second_circle, mirror_axes=V(1, 0), create_copy=True
)
items_2d.extend([circle_first, circle_second, polyline, mirrored_polyline])
representation_3d = builder.get_representation(self.representations["model_body"], items_3d)
representation_2d = builder.get_representation(self.representations["plan_body"], items_2d)
return representation_3d, representation_2d
overall_width, overall_depth, overall_height = (595.0, 680.0, 850.0)
representation_3d, representation_2d = create_dryer_machine(overall_width, overall_depth, overall_height)
self.create_explicit_type("IfcElectricApplianceType", "Neufert Drier", representation_3d, representation_2d)
parking_lots_data = {
"30 Deg Bay Class 1/1A No Overhang": (2100, 5400, 2000),
"30 Deg Bay Class 1/1A With Overhang": (2100, 5400, 2000),
"30 Deg Bay Class 1/1A With Wheelstop": (2100, 5400, 2000),
"30 Deg Bay Class 2 No Overhang": (2300, 5400, 2000),
"30 Deg Bay Class 2 With Overhang": (2300, 5400, 2000),
"30 Deg Bay Class 2 With Wheelstop": (2300, 5400, 2000),
"30 Deg Bay Class 3 No Overhang": (2500, 5400, 2000),
"30 Deg Bay Class 3 With Overhang": (2500, 5400, 2000),
"30 Deg Bay Class 3 With Wheelstop": (2500, 5400, 2000),
"30 Deg Bay Class 3A No Overhang": (2500, 5400, 2000),
"30 Deg Bay Class 3A With Overhang": (2500, 5400, 2000),
"30 Deg Bay Class 3A With Wheelstop": (2500, 5400, 2000),
"45 Deg Bay Class 1/1A No Overhang": (2400, 5400, 2000),
"45 Deg Bay Class 1/1A With Overhang": (2400, 5400, 2000),
"45 Deg Bay Class 1/1A With Wheelstop": (2400, 5400, 2000),
"45 Deg Bay Class 2 No Overhang": (2500, 5400, 2000),
"45 Deg Bay Class 2 With Overhang": (2500, 5400, 2000),
"45 Deg Bay Class 2 With Wheelstop": (2500, 5400, 2000),
"45 Deg Bay Class 3 No Overhang": (2600, 5400, 2000),
"45 Deg Bay Class 3 With Overhang": (2600, 5400, 2000),
"45 Deg Bay Class 3 With Wheelstop": (2600, 5400, 2000),
"45 Deg Bay Class 3A No Overhang": (2600, 5400, 2000),
"45 Deg Bay Class 3A With Overhang": (2600, 5400, 2000),
"45 Deg Bay Class 3A With Wheelstop": (2600, 5400, 2000),
"60 Deg Bay Class 1/1A No Overhang": (2400, 5400, 2000),
"60 Deg Bay Class 1/1A With Overhang": (2400, 5400, 2000),
"60 Deg Bay Class 1/1A With Wheelstop": (2400, 5400, 2000),
"60 Deg Bay Class 2 No Overhang": (2500, 5400, 2000),
"60 Deg Bay Class 2 With Overhang": (2500, 5400, 2000),
"60 Deg Bay Class 2 With Wheelstop": (2500, 5400, 2000),
"60 Deg Bay Class 3 No Overhang": (2600, 5400, 2000),
"60 Deg Bay Class 3 With Overhang": (2600, 5400, 2000),
"60 Deg Bay Class 3 With Wheelstop": (2600, 5400, 2000),
"60 Deg Bay Class 3A No Overhang": (2600, 5400, 2000),
"60 Deg Bay Class 3A With Overhang": (2600, 5400, 2000),
"60 Deg Bay Class 3A With Wheelstop": (2600, 5400, 2000),
"90 Deg Bay Class 1 No Overhang": (2400, 5400, 2000),
"90 Deg Bay Class 1 With Overhang": (2400, 4800, 2000),
"90 Deg Bay Class 1 With Wheelstop": (2400, 5400, 2000),
"90 Deg Bay Class 1A No Overhang": (2400, 5400, 2000),
"90 Deg Bay Class 1A With Overhang": (2400, 4800, 2000),
"90 Deg Bay Class 1A With Wheelstop": (2400, 5400, 2000),
"90 Deg Bay Class 2 No Overhang": (2500, 5400, 2000),
"90 Deg Bay Class 2 With Overhang": (2500, 4800, 2000),
"90 Deg Bay Class 2 With Wheelstop": (2500, 5400, 2000),
"90 Deg Bay Class 3 No Overhang": (2600, 5400, 2000),
"90 Deg Bay Class 3 With Overhang": (2600, 4800, 2000),
"90 Deg Bay Class 3 With Wheelstop": (2600, 5400, 2000),
"90 Deg Bay Class 3A Option 1 No Overhang": (2600, 5400, 2000),
"90 Deg Bay Class 3A Option 1 With Overhang": (2600, 4800, 2000),
"90 Deg Bay Class 3A Option 1 With Wheelstop": (2600, 5400, 2000),
"90 Deg Bay Class 3A Option 2 No Overhang": (2700, 5400, 2000),
"90 Deg Bay Class 3A Option 2 With Overhang": (2700, 4800, 2000),
"90 Deg Bay Class 3A Option 2 With Wheelstop": (2700, 5400, 2000),
"90 Deg Bay Motorcycle": (1200, 2500, 2000),
"3000 Aisle Parallel Bay": (2100, 6300, 2000),
"3300 Aisle Parallel Bay": (2100, 6100, 2000),
"3600 Aisle Parallel Bay": (2100, 5900, 2000),
"3000 Aisle Parallel Obstructed End Bay": (2100, 6600, 2000),
"3300 Aisle Parallel Obstructed End Bay": (2100, 6400, 2000),
"3600 Aisle Parallel Obstructed End Bay": (2100, 6200, 2000),
"3000 Aisle Parallel Unobstructed End Bay": (2100, 5400, 2000),
"3300 Aisle Parallel Unobstructed End Bay": (2100, 5400, 2000),
"3600 Aisle Parallel Unobstructed End Bay": (2100, 5400, 2000),
"3000 Aisle Parallel Unobstructed End Bay": (2100, 5000, 2000),
"3300 Aisle Parallel Unobstructed End Bay": (2100, 5000, 2000),
"3600 Aisle Parallel Unobstructed End Bay": (2100, 5000, 2000),
}
for parking_lot_name in parking_lots_data:
parameters = [float(i) for i in parking_lots_data[parking_lot_name]]
overall_width, overall_depth, overall_height = parameters
representation_3d, representation_2d = create_box_objects(
overall_width, overall_depth, overall_height, return_representations=True
)
self.create_explicit_type(
"IfcSpaceType", parking_lot_name, representation_3d, representation_2d, PredefinedType="PARKING"
)
self.file.write(output_filename)
def create_explicit_type(self, ifc_class, name, representation_3d, representation_2d, **params):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=ifc_class, name=name)
for param, value in params.items():
setattr(element, param, value)
ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=element, representation=representation_3d
)
ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=element, representation=representation_2d
)
ifcopenshell.api.run("project.assign_declaration", self.file, definition=element, relating_context=self.library)
return element
def create_layer_set_type(self, name, data):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=data["type"], name=name)
element.Description = data["Description"]
rel = ifcopenshell.api.run("material.assign_material", self.file, product=element, type="IfcMaterialLayerSet")
layer_set = rel.RelatingMaterial
for layer_data in data["Layers"]:
layer = ifcopenshell.api.run(
"material.add_layer", self.file, layer_set=layer_set, material=self.materials[layer_data[1]]["ifc"]
)
layer.Name = layer_data[0]
layer.LayerThickness = layer_data[2]
ifcopenshell.api.run("project.assign_declaration", self.file, definition=element, relating_context=self.library)
return element
def create_layer_type(self, ifc_class, name, thickness):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=ifc_class, name=name)
rel = ifcopenshell.api.run("material.assign_material", self.file, product=element, type="IfcMaterialLayerSet")
layer_set = rel.RelatingMaterial
layer = ifcopenshell.api.run(
"material.add_layer", self.file, layer_set=layer_set, material=self.materials["TBD"]["ifc"]
)
layer.LayerThickness = thickness
ifcopenshell.api.run("project.assign_declaration", self.file, definition=element, relating_context=self.library)
return element
def create_profile_type(self, ifc_class, name, profile):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=ifc_class, name=name)
rel = ifcopenshell.api.run("material.assign_material", self.file, product=element, type="IfcMaterialProfileSet")
profile_set = rel.RelatingMaterial
material_profile = ifcopenshell.api.run(
"material.add_profile",
self.file,
profile_set=profile_set,
material=self.material
# material=self.materials["TBD"]["ifc"]
)
ifcopenshell.api.run("material.assign_profile", self.file, material_profile=material_profile, profile=profile)
ifcopenshell.api.run("project.assign_declaration", self.file, definition=element, relating_context=self.library)
def create_type(self, ifc_class, name, representations):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=ifc_class, name=name)
for rep_name, obj_name in representations.items():
obj = bpy.data.objects.get(obj_name)
representation = ifcopenshell.api.run(
"geometry.add_representation",
self.file,
context=self.representations[rep_name],
blender_object=obj,
geometry=obj.data,
total_items=max(1, len(obj.material_slots)),
)
styles = []
for slot in obj.material_slots:
style = ifcopenshell.api.run("style.add_style", self.file, name=slot.material.name)
ifcopenshell.api.run(
"style.add_surface_style",
self.file,
style=style,
ifc_class="IfcSurfaceStyleRendering",
attributes=tool.Style.get_surface_rendering_attributes(slot.material),
)
styles.append(style)
if styles:
ifcopenshell.api.run(
"style.assign_representation_styles", self.file, shape_representation=representation, styles=styles
)
ifcopenshell.api.run(
"geometry.assign_representation", self.file, product=element, representation=representation
)
ifcopenshell.api.run("project.assign_declaration", self.file, definition=element, relating_context=self.library)
if __name__ == "__main__":
path = Path(__file__).parents[1] / "blenderbim/bim/data/libraries"
LibraryGenerator().generate(output_filename=str(path / "IFC4 AU Library.ifc"))