mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-16 18:44:47 +00:00
47f57d20cd
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)
2068 lines
95 KiB
Python
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"))
|