Files
IfcOpenShell/src/blenderbim/scripts/generate_furniture_library.py
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

2047 lines
94 KiB
Python
Raw Normal View History

# 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
import boltspy as bolts
from math import cos, tan, pi
from pathlib import Path
from mathutils import Vector
from itertools import chain
2023-01-08 13:32:13 +05:00
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([0, len(points) - 1])
# 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):
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 = []
seat = builder.rectangle(size=V(width, depth))
chair_back = builder.rectangle(size=V(width, thickness))
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
)
builder.translate([seat, chair_back] + legs, shift_to_center)
builder.mirror([seat, chair_back] + legs, mirror_axis)
seat = builder.extrude(
builder.profile(seat), thickness, position=V(0, 0, seat_level), extrusion_vector=V(0, 0, -1)
)
chair_back = builder.extrude(
builder.profile(chair_back), height - seat_level, position=V(0, 0, height), extrusion_vector=V(0, 0, -1)
)
legs = [builder.extrude(leg, seat_level - thickness) for leg in legs]
items_3d = [seat, chair_back] + 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))
2023-01-08 13:19:37 +05:00
builder.translate([polyline, first_semicircle, second_semicircle], shift_to_center)
builder.translate([polyline, first_semicircle, second_semicircle], V(0, -depth))
2023-01-08 13:19:37 +05:00
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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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=(1, 2), 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(
"IfcFurnitureType", "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(
"IfcFurnitureType", "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)
representation_3d, representation_2d = create_box_objects(width, depth, height, return_representations=True)
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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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=(50.0, 150.0, 150.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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", "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(
"IfcFurnitureType", "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("IfcFurnitureType", "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("IfcFurnitureType", 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("IfcFurnitureType", "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("IfcFurnitureType", "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)
self.file.write(output_filename)
def create_explicit_type(self, ifc_class, name, representation_3d, representation_2d):
element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class=ifc_class, name=name)
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"
2023-01-08 13:19:37 +05:00
LibraryGenerator().generate(output_filename=str(path / "IFC4 AU Library.ifc"))