mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 18:43:26 +00:00
Run black on BBIM
This commit is contained in:
+2
-1
@@ -1,6 +1,7 @@
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
extend-exclude = 'src/ifcopenshell-python/ifcopenshell/express/*'
|
||||
include = 'src/(bcf|bcfserver|blenderbim|bsdd|foundationserver|ifc2ca|ifc4d|ifc5d|ifcbimtester|ifcblender|ifccityjson|ifcclash|ifccsv|ifcdiff|ifcfm|ifcpatch|ifctester|ifcopenshell-python|ifcsverchok|opencdeserver)/.*.py$'
|
||||
extend-exclude = '(src/ifcopenshell-python/ifcopenshell/express/*|src/ifc2ca/templates/*)'
|
||||
|
||||
[tool.pyright]
|
||||
reportInvalidTypeForm = false
|
||||
|
||||
@@ -75,7 +75,7 @@ class AggregateData:
|
||||
return []
|
||||
if not element:
|
||||
return []
|
||||
|
||||
|
||||
product_linked_agg_group = [
|
||||
r
|
||||
for r in getattr(aggregate, "HasAssignments", []) or []
|
||||
@@ -85,7 +85,6 @@ class AggregateData:
|
||||
|
||||
if not product_linked_agg_group:
|
||||
return []
|
||||
|
||||
|
||||
total = len(product_linked_agg_group[0].RelatedObjects)
|
||||
return total
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ class BIM_PT_aggregate(Panel):
|
||||
op = row.operator("bim.select_parts", icon="RESTRICT_SELECT_OFF", text="")
|
||||
op.obj = context.active_object.name
|
||||
|
||||
|
||||
|
||||
class BIM_PT_linked_aggregate(Panel):
|
||||
bl_label = "Linked Aggregates"
|
||||
bl_idname = "BIM_PT_linked_aggregate"
|
||||
@@ -133,9 +133,8 @@ class BIM_PT_linked_aggregate(Panel):
|
||||
props = obj.BIMObjectAggregateProperties
|
||||
row = layout.row(align=True)
|
||||
|
||||
|
||||
if element.Decomposes:
|
||||
Number_Linked_Aggregates = AggregateData.data['total_linked_aggregate']
|
||||
Number_Linked_Aggregates = AggregateData.data["total_linked_aggregate"]
|
||||
if not Number_Linked_Aggregates:
|
||||
row.label(text="Not a Linked Aggregate")
|
||||
else:
|
||||
@@ -151,6 +150,3 @@ class BIM_PT_linked_aggregate(Panel):
|
||||
op = row.operator("bim.break_link_to_other_aggregates", text="", icon="X")
|
||||
else:
|
||||
row.label(text="Not an Aggregate")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ def draw_ui(context, layout, attributes):
|
||||
row.label(text=attribute["name"])
|
||||
# row.label(text=attribute["value"])
|
||||
op = row.operator("bim.select_similar", text=attribute["value"], icon="NONE", emboss=False)
|
||||
op.key = attribute['name']
|
||||
|
||||
op.key = attribute["name"]
|
||||
|
||||
# TODO: reimplement, see #1222
|
||||
# if "IfcSite/" in context.active_object.name or "IfcBuilding/" in context.active_object.name:
|
||||
|
||||
@@ -66,10 +66,7 @@ class LoadBcfProject(bpy.types.Operator):
|
||||
if bcfxml.version.version_id.startswith("2"):
|
||||
print("No project, we will create one for BBIM.")
|
||||
bcfxml.project_info = bcf.v2.model.ProjectExtension(
|
||||
project=bcf.v2.model.Project(
|
||||
name=nameless,
|
||||
project_id=str(uuid.uuid4())
|
||||
), extension_schema=""
|
||||
project=bcf.v2.model.Project(name=nameless, project_id=str(uuid.uuid4())), extension_schema=""
|
||||
)
|
||||
if bcfxml.project.name is None:
|
||||
bcfxml.project.name = nameless
|
||||
@@ -971,13 +968,14 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
self.set_colours(viewpoint)
|
||||
|
||||
def set_exceptions(self, viewpoint, context):
|
||||
if (
|
||||
not hasattr(viewpoint.visualization_info.components, "visibility")
|
||||
or not hasattr(viewpoint.visualization_info.components.visibility.exceptions, "component")
|
||||
if not hasattr(viewpoint.visualization_info.components, "visibility") or not hasattr(
|
||||
viewpoint.visualization_info.components.visibility.exceptions, "component"
|
||||
):
|
||||
return
|
||||
|
||||
exception_global_ids = {v.ifc_guid for v in viewpoint.visualization_info.components.visibility.exceptions.component or []}
|
||||
exception_global_ids = {
|
||||
v.ifc_guid for v in viewpoint.visualization_info.components.visibility.exceptions.component or []
|
||||
}
|
||||
|
||||
# print("default_visibility: {}".format(viewpoint.visualization_info.components.visibility.default_visibility))
|
||||
if viewpoint.visualization_info.components.visibility.default_visibility:
|
||||
@@ -1034,7 +1032,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
context.area.type = old
|
||||
|
||||
def set_openings_visibility(self, is_visible, context):
|
||||
pass # We no longer have an openings collection
|
||||
pass # We no longer have an openings collection
|
||||
|
||||
def set_selection(self, viewpoint):
|
||||
if not viewpoint.visualization_info.components or not viewpoint.visualization_info.components.selection:
|
||||
@@ -1147,7 +1145,7 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
# https://github.com/buildingSMART/BCF-XML/tree/release_3_0/Documentation#coloring
|
||||
if lv == 8:
|
||||
t = tuple(int(value[i : i + lv // 4], 16) for i in range(0, lv, lv // 4))
|
||||
col = [t[1] / 255.0, t[2] / 255.0, t[3] / 255.0, t[0] / 255.0]
|
||||
col = [t[1] / 255.0, t[2] / 255.0, t[3] / 255.0, t[0] / 255.0]
|
||||
else:
|
||||
t = tuple(int(value[i : i + lv // 3], 16) for i in range(0, lv, lv // 3))
|
||||
col = [t[0] / 255.0, t[1] / 255.0, t[2] / 255.0, 1]
|
||||
|
||||
@@ -603,7 +603,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
objs = context.selected_objects
|
||||
|
||||
if not any((element:=tool.Ifc.get_entity(obj)) and element.is_a("IfcSpace") for obj in objs):
|
||||
if not any((element := tool.Ifc.get_entity(obj)) and element.is_a("IfcSpace") for obj in objs):
|
||||
self.report({"INFO"}, "No IfcSpace elements selected.")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -166,9 +166,9 @@ class BrickschemaReferencesData:
|
||||
results.append(
|
||||
{
|
||||
"id": reference.id(),
|
||||
"identification": reference.ItemReference
|
||||
if tool.Ifc.get_schema() == "IFC2X3"
|
||||
else reference.Identification,
|
||||
"identification": (
|
||||
reference.ItemReference if tool.Ifc.get_schema() == "IFC2X3" else reference.Identification
|
||||
),
|
||||
"name": reference.Name or "Unnamed",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -34,6 +34,7 @@ import blenderbim.core.brick as core
|
||||
import blenderbim.tool.brick as tool
|
||||
from blenderbim.tool.brick import BrickStore
|
||||
|
||||
|
||||
def update_active_brick_index(self, context):
|
||||
BrickschemaData.is_loaded = False
|
||||
|
||||
@@ -53,7 +54,7 @@ def get_brick_entity_classes(self, context):
|
||||
return [(uri, uri.split("#")[-1], "") for uri in BrickStore.entity_classes[entity]]
|
||||
|
||||
|
||||
def get_brick_roots(self, context):
|
||||
def get_brick_roots(self, context):
|
||||
return [(root, root, "") for root in BrickStore.root_classes]
|
||||
|
||||
|
||||
@@ -64,13 +65,13 @@ def get_brick_relations(self, context):
|
||||
return relations
|
||||
relations.append(("http://www.w3.org/2000/01/rdf-schema#label", "label", ""))
|
||||
return relations
|
||||
|
||||
|
||||
|
||||
def update_view(self, context):
|
||||
root = context.scene.BIMBrickProperties.brick_list_root
|
||||
core.set_brick_list_root(tool.Brick, brick_root=root, split_screen=False)
|
||||
|
||||
|
||||
def split_screen_update_view(self, context):
|
||||
root = context.scene.BIMBrickProperties.split_screen_brick_list_root
|
||||
core.set_brick_list_root(tool.Brick, brick_root=root, split_screen=True)
|
||||
@@ -108,7 +109,11 @@ class BIMBrickProperties(PropertyGroup):
|
||||
# create relations split screen
|
||||
split_screen_toggled: BoolProperty(name="Split Screen Toggled", default=False)
|
||||
split_screen_bricks: CollectionProperty(name="Split Screen Bricks", type=Brick)
|
||||
split_screen_active_brick_index: IntProperty(name="Split Screen Active Brick Index", update=update_active_brick_index)
|
||||
split_screen_active_brick_index: IntProperty(
|
||||
name="Split Screen Active Brick Index", update=update_active_brick_index
|
||||
)
|
||||
split_screen_active_brick_class: StringProperty(name="Split Screen Active Brick Class")
|
||||
split_screen_brick_breadcrumbs: CollectionProperty(name="Split Screen Brick Breadcrumbs", type=StrProperty)
|
||||
split_screen_brick_list_root: EnumProperty(name="Split Screen Brick List Root", items=get_brick_roots, update=split_screen_update_view)
|
||||
split_screen_brick_list_root: EnumProperty(
|
||||
name="Split Screen Brick List Root", items=get_brick_roots, update=split_screen_update_view
|
||||
)
|
||||
|
||||
@@ -46,7 +46,7 @@ class BIM_PT_brickschema_project_info(Panel):
|
||||
|
||||
def draw(self, context):
|
||||
self.props = context.scene.BIMBrickProperties
|
||||
|
||||
|
||||
if not BrickschemaData.data["is_loaded"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.new_brick_file", text="Create Project")
|
||||
@@ -58,7 +58,7 @@ class BIM_PT_brickschema_project_info(Panel):
|
||||
row.label(text=BrickStore.path, icon="FILEBROWSER")
|
||||
else:
|
||||
row.label(text="No file", icon="FILEBROWSER")
|
||||
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
if BrickStore.last_saved:
|
||||
row.label(text=BrickStore.last_saved, icon="TIME")
|
||||
@@ -130,7 +130,7 @@ class BIM_PT_brickschema_create_entity(Panel):
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
prop_with_search(row, self.props, "brick_entity_class", text="Type")
|
||||
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
active = tool.Ifc.get_entity(context.active_object)
|
||||
if active and context.selected_objects:
|
||||
@@ -141,7 +141,7 @@ class BIM_PT_brickschema_create_entity(Panel):
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.add_brick", text="Create Entity")
|
||||
|
||||
|
||||
|
||||
class BIM_PT_brickschema_viewport(Panel):
|
||||
bl_label = "Viewport"
|
||||
@@ -194,7 +194,9 @@ class BIM_PT_brickschema_viewport(Panel):
|
||||
|
||||
row = grid_right.row()
|
||||
BIM_UL_bricks.split_screen = True
|
||||
row.template_list("BIM_UL_bricks", "", self.props, "split_screen_bricks", self.props, "split_screen_active_brick_index")
|
||||
row.template_list(
|
||||
"BIM_UL_bricks", "", self.props, "split_screen_bricks", self.props, "split_screen_active_brick_index"
|
||||
)
|
||||
|
||||
if BrickschemaData.data["active_relations"]:
|
||||
row = self.layout.row(align=True)
|
||||
@@ -213,7 +215,13 @@ class BIM_PT_brickschema_viewport(Panel):
|
||||
row.label(text="No selection", icon="INFO")
|
||||
else:
|
||||
prop_with_search(row, self.props, "new_brick_relation_type", text="")
|
||||
row.label(text=split_screen_selection.label if split_screen_selection.label else split_screen_selection.name)
|
||||
row.label(
|
||||
text=(
|
||||
split_screen_selection.label
|
||||
if split_screen_selection.label
|
||||
else split_screen_selection.name
|
||||
)
|
||||
)
|
||||
row.operator("bim.add_brick_relation", text="", icon="ADD")
|
||||
|
||||
elif self.props.brick_create_relations_toggled:
|
||||
@@ -234,7 +242,11 @@ class BIM_PT_brickschema_viewport(Panel):
|
||||
row.label(text=relation["object_name"])
|
||||
row = split.row(align=True)
|
||||
row.column().alignment = "RIGHT"
|
||||
if self.props.brick_edit_relations_toggled and relation["predicate_uri"] and relation["predicate_name"] != "type":
|
||||
if (
|
||||
self.props.brick_edit_relations_toggled
|
||||
and relation["predicate_uri"]
|
||||
and relation["predicate_name"] != "type"
|
||||
):
|
||||
op = row.operator("bim.remove_brick_relation", text="", icon="UNLINKED")
|
||||
op.predicate = relation["predicate_uri"]
|
||||
op.object = relation["object_uri"]
|
||||
@@ -263,6 +275,7 @@ class BIM_UL_bricks(UIList):
|
||||
row = split.row()
|
||||
row.label(text=str(item.total_items))
|
||||
|
||||
|
||||
class BIM_PT_ifc_brickschema_references(Panel):
|
||||
bl_label = "Brickschema References"
|
||||
bl_idname = "BIM_PT_ifc_brickschema_references"
|
||||
@@ -291,13 +304,13 @@ class BIM_PT_ifc_brickschema_references(Panel):
|
||||
row.label(text="No IFC Libraries")
|
||||
row.operator("bim.convert_brick_project", text="", icon="ADD")
|
||||
return
|
||||
|
||||
|
||||
elif not BrickschemaReferencesData.data["libraries"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="No IFC Libraries: save the Brick project to create a new library", icon="ERROR")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Libraries must have location pointing to a \".ttl\" file", icon="INFO")
|
||||
row.label(text='Libraries must have location pointing to a ".ttl" file', icon="INFO")
|
||||
return
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
@@ -318,4 +331,4 @@ class BIM_PT_ifc_brickschema_references(Panel):
|
||||
row.label(text=reference["identification"], icon="ASSET_MANAGER")
|
||||
row.label(text=reference["name"])
|
||||
row.operator("bim.unassign_library_reference", text="", icon="X").reference = reference["id"]
|
||||
row.operator("bim.view_brick_item", text="", icon="DISCLOSURE_TRI_RIGHT").item = reference["identification"]
|
||||
row.operator("bim.view_brick_item", text="", icon="DISCLOSURE_TRI_RIGHT").item = reference["identification"]
|
||||
|
||||
@@ -144,7 +144,7 @@ class CadFillet(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.radius = self.radius * si_conversion
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
|
||||
@@ -369,7 +369,7 @@ class CadOffset(bpy.types.Operator):
|
||||
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.distance = self.distance * si_conversion
|
||||
|
||||
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
|
||||
@@ -507,8 +507,6 @@ class CadOffset(bpy.types.Operator):
|
||||
local_direction = (rotation_i @ direction).normalized()
|
||||
normals.append(local_direction)
|
||||
|
||||
|
||||
|
||||
if len(normals) == 2:
|
||||
# https://stackoverflow.com/a/54042831/9627415
|
||||
new_normal = (normals[0].lerp(normals[1], 0.5)).normalized()
|
||||
@@ -638,7 +636,7 @@ class AddIfcArcIndexFillet(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.radius = self.radius * si_conversion
|
||||
|
||||
|
||||
if self.has_selected_existing_arc(context):
|
||||
self.change_radius(context)
|
||||
else:
|
||||
@@ -814,8 +812,8 @@ class AddRectangle(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.x = self.x * si_conversion
|
||||
self.y = self.y * si_conversion
|
||||
|
||||
self.y = self.y * si_conversion
|
||||
|
||||
obj = context.active_object
|
||||
bm = bmesh.from_edit_mesh(obj.data)
|
||||
cursor = obj.matrix_world.inverted() @ context.scene.cursor.location
|
||||
|
||||
@@ -70,7 +70,7 @@ class ClashDecorator:
|
||||
blf.color(font_id, *color)
|
||||
if coords_2d:
|
||||
w, h = blf.dimensions(font_id, text)
|
||||
coords_2d -= Vector((w * .5, 0))
|
||||
coords_2d -= Vector((w * 0.5, 0))
|
||||
blf.position(font_id, coords_2d[0], coords_2d[1], 0)
|
||||
blf.draw(font_id, text) # Set your text here
|
||||
|
||||
|
||||
@@ -496,4 +496,3 @@ class SelectSmartGroup(bpy.types.Operator):
|
||||
with bpy.context.temp_override(**context_override):
|
||||
bpy.ops.view3d.view_selected()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ class BIM_PT_object_constraints(Panel):
|
||||
if constraint["type"] == "IfcObjective":
|
||||
icon = "LIGHT"
|
||||
else:
|
||||
continue # Metric not implemented
|
||||
continue # Metric not implemented
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=constraint["name"])
|
||||
row.operator("bim.unassign_constraint", text="", icon="X").constraint = constraint["id"]
|
||||
|
||||
@@ -164,7 +164,14 @@ class CostSchedulesData:
|
||||
if unit:
|
||||
data["UnitSymbol"] = ifcopenshell.util.unit.get_unit_symbol(unit)
|
||||
if quantity.is_a("IfcPhysicalSimpleQuantity"):
|
||||
measure_class = quantity.wrapped_data.declaration().as_entity().attribute_by_index(3).type_of_attribute().declared_type().name()
|
||||
measure_class = (
|
||||
quantity.wrapped_data.declaration()
|
||||
.as_entity()
|
||||
.attribute_by_index(3)
|
||||
.type_of_attribute()
|
||||
.declared_type()
|
||||
.name()
|
||||
)
|
||||
if "Count" in measure_class:
|
||||
data["UnitSymbol"] = "U"
|
||||
|
||||
|
||||
@@ -47,14 +47,14 @@ class BIM_PT_cost_schedules(Panel):
|
||||
row = self.layout.row(align=True)
|
||||
if CostSchedulesData.data["total_cost_schedules"]:
|
||||
row.alignment = "RIGHT"
|
||||
row.operator("bim.export_cost_schedules",icon="EXPORT",text="Export All Schedules")
|
||||
row.operator("bim.export_cost_schedules", icon="EXPORT", text="Export All Schedules")
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=f"{CostSchedulesData.data['total_cost_schedules']} Cost Schedules Found", icon="TEXT")
|
||||
else:
|
||||
row.label(text="No Cost Schedules found.", icon="TEXT")
|
||||
|
||||
row.operator("bim.add_cost_schedule", icon="ADD", text="")
|
||||
row.operator("bim.import_cost_schedule_csv",icon="IMPORT",text="")
|
||||
row.operator("bim.import_cost_schedule_csv", icon="IMPORT", text="")
|
||||
|
||||
for schedule in CostSchedulesData.data["schedules"]:
|
||||
self.draw_cost_schedule_ui(schedule)
|
||||
@@ -96,9 +96,9 @@ class BIM_PT_cost_schedules(Panel):
|
||||
text="{}[{}]".format(cost_schedule["name"], cost_schedule["predefined_type"]), icon="LINENUMBERS_ON"
|
||||
)
|
||||
row.operator("bim.enable_editing_cost_items", text="", icon="OUTLINER").cost_schedule = cost_schedule["id"]
|
||||
row.operator(
|
||||
"bim.enable_editing_cost_schedule_attributes", text="", icon="GREASEPENCIL"
|
||||
).cost_schedule = cost_schedule["id"]
|
||||
row.operator("bim.enable_editing_cost_schedule_attributes", text="", icon="GREASEPENCIL").cost_schedule = (
|
||||
cost_schedule["id"]
|
||||
)
|
||||
row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule["id"]
|
||||
if self.props.active_cost_schedule_id == cost_schedule["id"]:
|
||||
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
|
||||
@@ -616,9 +616,9 @@ class BIM_UL_cost_items_trait:
|
||||
def draw_parent_operator(self, row, cost_item_id):
|
||||
if self.props.active_cost_item_id:
|
||||
if self.props.active_cost_item_id != cost_item_id:
|
||||
op = row.operator(
|
||||
"bim.change_parent_cost_item", text="", icon="LINKED", emboss=False
|
||||
).new_parent = cost_item_id
|
||||
op = row.operator("bim.change_parent_cost_item", text="", icon="LINKED", emboss=False).new_parent = (
|
||||
cost_item_id
|
||||
)
|
||||
else:
|
||||
row.label(text="", icon="BLANK1")
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
|
||||
import bpy
|
||||
from blenderbim.bim.prop import StrProperty, Attribute
|
||||
#from blenderbim.bim.module.spatial.data import SpatialData
|
||||
|
||||
# from blenderbim.bim.module.spatial.data import SpatialData
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
@@ -30,10 +31,13 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
#import blenderbim.tool as tool
|
||||
#import blenderbim.core.geometry
|
||||
#import ifcopenshell
|
||||
|
||||
# import blenderbim.tool as tool
|
||||
# import blenderbim.core.geometry
|
||||
# import ifcopenshell
|
||||
|
||||
|
||||
class BIMCoveringProperties(PropertyGroup):
|
||||
ceiling_height: bpy.props.FloatProperty(name="ceiling_height", default=2.7, subtype="DISTANCE", description="Ceiling height")
|
||||
ceiling_height: bpy.props.FloatProperty(
|
||||
name="ceiling_height", default=2.7, subtype="DISTANCE", description="Ceiling height"
|
||||
)
|
||||
|
||||
@@ -89,7 +89,7 @@ class BIM_PT_ifccsv(Panel):
|
||||
|
||||
row = layout.row(align=True)
|
||||
op = row.operator("bim.search", text="Select", icon="VIEWZOOM")
|
||||
op.property_group = "CsvProperties"
|
||||
op.property_group = "CsvProperties"
|
||||
layout.separator()
|
||||
|
||||
row = layout.row(align=True)
|
||||
@@ -128,6 +128,3 @@ class BIM_PT_ifccsv(Panel):
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.export_ifccsv", icon="EXPORT", text="Export IFC to " + props.format.upper())
|
||||
row.operator("bim.import_ifccsv", icon="IMPORT")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -90,9 +90,9 @@ class BIM_PT_debug(Panel):
|
||||
row.operator("bim.select_high_polygon_meshes").threshold = context.scene.BIMDebugProperties.number_of_polygons
|
||||
row.prop(props, "number_of_polygons", text="")
|
||||
row = layout.split(factor=0.7, align=True)
|
||||
row.operator(
|
||||
"bim.select_highest_polygon_meshes"
|
||||
).percentile = context.scene.BIMDebugProperties.percentile_of_polygons
|
||||
row.operator("bim.select_highest_polygon_meshes").percentile = (
|
||||
context.scene.BIMDebugProperties.percentile_of_polygons
|
||||
)
|
||||
row.prop(props, "percentile_of_polygons", text="")
|
||||
|
||||
row = layout.split(factor=0.5, align=True)
|
||||
@@ -140,9 +140,9 @@ class BIM_PT_debug(Panel):
|
||||
op = row.operator("bim.print_object_placement", icon="OBJECT_ORIGIN", text="")
|
||||
op.step_id = attribute.int_value
|
||||
if attribute.int_value:
|
||||
row.operator(
|
||||
"bim.inspect_from_step_id", icon="DISCLOSURE_TRI_RIGHT", text=""
|
||||
).step_id = attribute.int_value
|
||||
row.operator("bim.inspect_from_step_id", icon="DISCLOSURE_TRI_RIGHT", text="").step_id = (
|
||||
attribute.int_value
|
||||
)
|
||||
|
||||
if props.inverse_attributes:
|
||||
layout.label(text="Inverse attributes:")
|
||||
@@ -152,9 +152,9 @@ class BIM_PT_debug(Panel):
|
||||
row.prop(attribute, "name", text="")
|
||||
row.prop(attribute, "string_value", text="")
|
||||
if attribute.int_value:
|
||||
row.operator(
|
||||
"bim.inspect_from_step_id", icon="DISCLOSURE_TRI_RIGHT", text=""
|
||||
).step_id = attribute.int_value
|
||||
row.operator("bim.inspect_from_step_id", icon="DISCLOSURE_TRI_RIGHT", text="").step_id = (
|
||||
attribute.int_value
|
||||
)
|
||||
|
||||
if props.inverse_references:
|
||||
layout.label(text="Inverse references:")
|
||||
@@ -163,6 +163,6 @@ class BIM_PT_debug(Panel):
|
||||
row = layout.row(align=True)
|
||||
row.prop(attribute, "string_value", text="")
|
||||
if attribute.int_value:
|
||||
row.operator(
|
||||
"bim.inspect_from_step_id", icon="DISCLOSURE_TRI_RIGHT", text=""
|
||||
).step_id = attribute.int_value
|
||||
row.operator("bim.inspect_from_step_id", icon="DISCLOSURE_TRI_RIGHT", text="").step_id = (
|
||||
attribute.int_value
|
||||
)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
import bpy
|
||||
from blenderbim.bim.module.demo.data import DemoData
|
||||
|
||||
|
||||
# Every panel in the interface correlates to one of these classes. If you enable
|
||||
# the "Developer Extras" option in Blender, then you can actually right click on
|
||||
# any panel in Blender, and click "Edit Source". This will bring you to a ui.py
|
||||
|
||||
@@ -159,7 +159,7 @@ class BaseDecorator:
|
||||
objecttype = "NOTDEFINED"
|
||||
|
||||
def __init__(self):
|
||||
self.font_id = 0 # 0 is the default font
|
||||
self.font_id = 0 # 0 is the default font
|
||||
|
||||
# POLYLINE_UNIFORM_COLOR is good for smoothed lines since `bgl.enable(GL_LINE_SMOOTH)` is deprecated
|
||||
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
||||
@@ -2020,7 +2020,6 @@ class DecorationsHandler:
|
||||
for decorator in self.decorators.values():
|
||||
decorator.font_id = font_id
|
||||
|
||||
|
||||
def get_objects_and_decorators(self, collection):
|
||||
# TODO: do it in data instead of the handler for performance?
|
||||
results = []
|
||||
|
||||
@@ -41,9 +41,8 @@ def set_active_camera_resolution(scene):
|
||||
props = scene.camera.data.BIMCameraProperties
|
||||
ortho_scale = max((props.width, props.height))
|
||||
aspect_ratio = props.width / props.height
|
||||
if (
|
||||
(scene.camera.data.ortho_scale != ortho_scale)
|
||||
or (scene.render.resolution_x / scene.render.resolution_y != aspect_ratio)
|
||||
if (scene.camera.data.ortho_scale != ortho_scale) or (
|
||||
scene.render.resolution_x / scene.render.resolution_y != aspect_ratio
|
||||
):
|
||||
scene.camera.data.ortho_scale = ortho_scale
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ def format_distance(
|
||||
precision=None,
|
||||
decimal_places=None,
|
||||
suppress_zero_inches=False,
|
||||
in_unit_length = False
|
||||
in_unit_length=False,
|
||||
):
|
||||
s_code = "\u00b2" # Superscript two THIS IS LEGACY (but being kept for when Area Measurements are re-implimented)
|
||||
|
||||
@@ -141,9 +141,9 @@ def format_distance(
|
||||
# Imperial Formatting
|
||||
if unit_system == "IMPERIAL":
|
||||
if in_unit_length:
|
||||
if unit_length == 'INCHES':
|
||||
if unit_length == "INCHES":
|
||||
toInches = 1
|
||||
if unit_length == 'FEET':
|
||||
if unit_length == "FEET":
|
||||
toInches = 11.9999
|
||||
else:
|
||||
toInches = 39.3700787401574887
|
||||
@@ -222,11 +222,11 @@ def format_distance(
|
||||
# METRIC FORMATTING
|
||||
elif unit_system == "METRIC":
|
||||
if in_unit_length:
|
||||
if unit_length == 'CENTIMETERS':
|
||||
value = value/100
|
||||
if unit_length == 'MILLIMETERS':
|
||||
value = value/1000
|
||||
|
||||
if unit_length == "CENTIMETERS":
|
||||
value = value / 100
|
||||
if unit_length == "MILLIMETERS":
|
||||
value = value / 1000
|
||||
|
||||
if precision:
|
||||
value = precision * round(float(value) / precision)
|
||||
|
||||
|
||||
@@ -560,7 +560,7 @@ class Scheduler:
|
||||
|
||||
text_tag = self.svg.text("", **(text_params | {"font-size": "0"} | box_alignment_params))
|
||||
|
||||
# TODO: Should be done without using magic number for self.font_width
|
||||
# TODO: Should be done without using magic number for self.font_width
|
||||
if wrap_text:
|
||||
wrapped_lines = []
|
||||
for line in text_lines:
|
||||
|
||||
@@ -123,18 +123,18 @@ class BIM_PT_element_filters(Panel):
|
||||
self.layout, props.include_filter_groups, ElementFiltersData, "drawing_include"
|
||||
)
|
||||
row = self.layout.row(align=True)
|
||||
row.operator(
|
||||
"bim.edit_element_filter", icon="CHECKMARK", text="Save Include Filter"
|
||||
).filter_mode = "INCLUDE"
|
||||
row.operator("bim.edit_element_filter", icon="CHECKMARK", text="Save Include Filter").filter_mode = (
|
||||
"INCLUDE"
|
||||
)
|
||||
row.operator("bim.enable_editing_element_filter", icon="CANCEL", text="").filter_mode = "NONE"
|
||||
elif props.filter_mode == "EXCLUDE":
|
||||
blenderbim.bim.helper.draw_filter(
|
||||
self.layout, props.exclude_filter_groups, ElementFiltersData, "drawing_exclude"
|
||||
)
|
||||
row = self.layout.row(align=True)
|
||||
row.operator(
|
||||
"bim.edit_element_filter", icon="CHECKMARK", text="Save Exclude Filter"
|
||||
).filter_mode = "EXCLUDE"
|
||||
row.operator("bim.edit_element_filter", icon="CHECKMARK", text="Save Exclude Filter").filter_mode = (
|
||||
"EXCLUDE"
|
||||
)
|
||||
row.operator("bim.enable_editing_element_filter", icon="CANCEL", text="").filter_mode = "NONE"
|
||||
else:
|
||||
row = self.layout.row(align=True)
|
||||
@@ -260,9 +260,9 @@ class BIM_PT_drawings(Panel):
|
||||
row2 = col.row(align=True)
|
||||
row2.operator("bim.remove_drawing", icon="X", text="").drawing = active_drawing.ifc_definition_id
|
||||
|
||||
row2.operator(
|
||||
"bim.duplicate_drawing", icon="COPYDOWN", text=""
|
||||
).drawing = active_drawing.ifc_definition_id
|
||||
row2.operator("bim.duplicate_drawing", icon="COPYDOWN", text="").drawing = (
|
||||
active_drawing.ifc_definition_id
|
||||
)
|
||||
|
||||
col = row.column()
|
||||
col.alignment = "RIGHT"
|
||||
@@ -339,9 +339,9 @@ class BIM_PT_schedules(Panel):
|
||||
row = self.layout.row(align=True)
|
||||
row.alignment = "RIGHT"
|
||||
row.operator("bim.open_schedule", icon="URL", text="").schedule = active_schedule.ifc_definition_id
|
||||
row.operator(
|
||||
"bim.build_schedule", icon="LINENUMBERS_ON", text=""
|
||||
).schedule = active_schedule.ifc_definition_id
|
||||
row.operator("bim.build_schedule", icon="LINENUMBERS_ON", text="").schedule = (
|
||||
active_schedule.ifc_definition_id
|
||||
)
|
||||
row.operator("bim.remove_schedule", icon="X", text="").schedule = active_schedule.ifc_definition_id
|
||||
|
||||
self.layout.template_list(
|
||||
@@ -612,13 +612,13 @@ class BIM_UL_sheets(bpy.types.UIList):
|
||||
row = layout.row(align=True)
|
||||
if item.is_sheet:
|
||||
if item.is_expanded:
|
||||
row.operator(
|
||||
"bim.contract_sheet", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN"
|
||||
).sheet = item.ifc_definition_id
|
||||
row.operator("bim.contract_sheet", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN").sheet = (
|
||||
item.ifc_definition_id
|
||||
)
|
||||
else:
|
||||
row.operator(
|
||||
"bim.expand_sheet", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT"
|
||||
).sheet = item.ifc_definition_id
|
||||
row.operator("bim.expand_sheet", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT").sheet = (
|
||||
item.ifc_definition_id
|
||||
)
|
||||
|
||||
row.label(text=f"{item.identification} - {item.name}")
|
||||
else:
|
||||
|
||||
@@ -39,6 +39,7 @@ class SelectFMIfcFile(MultipleFileSelector):
|
||||
self.update_props(props, "ifc_file", props.ifc_files)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class ExecuteIfcFM(bpy.types.Operator):
|
||||
bl_idname = "bim.execute_ifcfm"
|
||||
bl_label = "Execute IfcFM"
|
||||
|
||||
@@ -85,15 +85,15 @@ class BIM_MT_object_set_origin(Menu):
|
||||
bl_label = "IFC Set Origin"
|
||||
|
||||
def draw(self, context):
|
||||
self.layout.operator(
|
||||
"bim.override_origin_set", icon="PLUGIN", text="IFC Geometry to Origin"
|
||||
).origin_type = "GEOMETRY_ORIGIN"
|
||||
self.layout.operator(
|
||||
"bim.override_origin_set", icon="PLUGIN", text="IFC Origin to Geometry"
|
||||
).origin_type = "ORIGIN_GEOMETRY"
|
||||
self.layout.operator(
|
||||
"bim.override_origin_set", icon="PLUGIN", text="IFC Origin to 3D Cursor"
|
||||
).origin_type = "ORIGIN_CURSOR"
|
||||
self.layout.operator("bim.override_origin_set", icon="PLUGIN", text="IFC Geometry to Origin").origin_type = (
|
||||
"GEOMETRY_ORIGIN"
|
||||
)
|
||||
self.layout.operator("bim.override_origin_set", icon="PLUGIN", text="IFC Origin to Geometry").origin_type = (
|
||||
"ORIGIN_GEOMETRY"
|
||||
)
|
||||
self.layout.operator("bim.override_origin_set", icon="PLUGIN", text="IFC Origin to 3D Cursor").origin_type = (
|
||||
"ORIGIN_CURSOR"
|
||||
)
|
||||
self.layout.operator(
|
||||
"bim.override_origin_set", icon="PLUGIN", text="IFC Origin to Center of Mass (Surface)"
|
||||
).origin_type = "ORIGIN_CENTER_OF_MASS"
|
||||
|
||||
@@ -118,6 +118,7 @@ class ConvertGlobalToLocal(bpy.types.Operator, tool.Ifc.Operator):
|
||||
def _execute(self, context):
|
||||
core.convert_global_to_local(tool.Georeference)
|
||||
|
||||
|
||||
class ConvertAngleToCoordinates(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.convert_angle_to_coord"
|
||||
bl_label = "Convert Angle To Y Axis"
|
||||
|
||||
@@ -101,9 +101,9 @@ class LibraryReferencesData:
|
||||
results.append(
|
||||
{
|
||||
"id": library.id(),
|
||||
"identification": library.ItemReference
|
||||
if tool.Ifc.get_schema() == "IFC2X3"
|
||||
else library.Identification,
|
||||
"identification": (
|
||||
library.ItemReference if tool.Ifc.get_schema() == "IFC2X3" else library.Identification
|
||||
),
|
||||
"name": library.Name or "Unnamed",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -34,10 +34,12 @@ classes = (
|
||||
ui.BIM_PT_solar,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.radiance_exporter_properties = bpy.props.PointerProperty(type=prop.RadianceExporterProperties)
|
||||
bpy.types.Scene.BIMSolarProperties = bpy.props.PointerProperty(type=prop.BIMSolarProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.radiance_exporter_properties
|
||||
del bpy.types.Scene.BIMSolarProperties
|
||||
|
||||
@@ -87,7 +87,6 @@ class SolarDecorator:
|
||||
blf.position(self.font_id, co[0], co[1], 0)
|
||||
blf.draw(self.font_id, line)
|
||||
|
||||
|
||||
def draw_geometry(self, context):
|
||||
self.addon_prefs = tool.Blender.get_addon_preferences()
|
||||
decorator_color_special = self.addon_prefs.decorator_color_special
|
||||
@@ -153,8 +152,7 @@ class SolarDecorator:
|
||||
analemma_verts = sun_position.sun_calc.calc_analemma(context, h)
|
||||
coords.extend([origin @ v for v in analemma_verts])
|
||||
for i in range(len(analemma_verts) - 1):
|
||||
indices.append((coord_offset + i,
|
||||
coord_offset + i+1))
|
||||
indices.append((coord_offset + i, coord_offset + i + 1))
|
||||
coord_offset += len(analemma_verts)
|
||||
|
||||
self.draw_batch("LINES", coords, decorator_color_special, indices)
|
||||
|
||||
@@ -37,12 +37,13 @@ from blenderbim.bim.module.light.data import SolarData
|
||||
|
||||
ifc_materials = []
|
||||
|
||||
|
||||
class ExportOBJ(bpy.types.Operator):
|
||||
"""Exports the IFC File to OBJ"""
|
||||
|
||||
bl_idname = "export_scene.radiance"
|
||||
bl_label = "Export"
|
||||
bl_description = "Export the IFC to OBJ"
|
||||
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
@@ -52,12 +53,11 @@ class ExportOBJ(bpy.types.Operator):
|
||||
|
||||
context.scene.radiance_exporter_properties.is_exporting = True
|
||||
|
||||
|
||||
# Conversion from IFC to OBJ
|
||||
# Settings for obj
|
||||
settings = ifcopenshell.geom.settings()
|
||||
serializer_settings = ifcopenshell.geom.serializer_settings()
|
||||
|
||||
|
||||
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.SURFACES_AND_SOLIDS)
|
||||
settings.set("apply-default-materials", True)
|
||||
serializer_settings.set("use-element-guids", True)
|
||||
@@ -65,17 +65,17 @@ class ExportOBJ(bpy.types.Operator):
|
||||
|
||||
if should_load_from_memory:
|
||||
ifc_file = tool.Ifc.get()
|
||||
|
||||
|
||||
else:
|
||||
ifc_file_path = context.scene.radiance_exporter_properties.ifc_file
|
||||
ifc_file = ifcopenshell.open(ifc_file_path)
|
||||
|
||||
|
||||
# for material in ifc_file.by_type("IfcMaterial"):
|
||||
# self.report({'INFO'}, f"Material: {material.Name}, ID: {material.id()}")
|
||||
|
||||
obj_file_path = os.path.join(output_dir, "model.obj")
|
||||
mtl_file_path = os.path.join(output_dir, "model.mtl")
|
||||
|
||||
|
||||
serialiser = ifcopenshell.geom.serializers.obj(obj_file_path, mtl_file_path, settings, serializer_settings)
|
||||
serialiser.setFile(ifc_file)
|
||||
serialiser.setUnitNameAndMagnitude("METER", 1.0)
|
||||
@@ -84,10 +84,10 @@ class ExportOBJ(bpy.types.Operator):
|
||||
if ifc_file.schema in ("IFC2X3", "IFC4"):
|
||||
elements = ifc_file.by_type("IfcElement") + ifc_file.by_type("IfcProxy")
|
||||
else:
|
||||
elements = ifc_file.by_type("IfcElement")
|
||||
elements = ifc_file.by_type("IfcElement")
|
||||
|
||||
elements = [e for e in elements if not e.is_a("IfcFeatureElement") or e.is_a("IfcSurfaceFeature")]
|
||||
|
||||
elements = [e for e in elements if not e.is_a("IfcFeatureElement") or e.is_a("IfcSurfaceFeature")]
|
||||
|
||||
iterator = ifcopenshell.geom.iterator(settings, ifc_file, multiprocessing.cpu_count(), include=elements)
|
||||
if iterator.initialize():
|
||||
while True:
|
||||
@@ -102,30 +102,31 @@ class ExportOBJ(bpy.types.Operator):
|
||||
# print(material, dir(material))
|
||||
# print(material.name)
|
||||
ifc_materials.append(material.name)
|
||||
|
||||
|
||||
serialiser.write(shape)
|
||||
if not iterator.next():
|
||||
break
|
||||
|
||||
|
||||
serialiser.finalize()
|
||||
context.scene.radiance_exporter_properties.is_exporting = False
|
||||
|
||||
self.report({'INFO'}, "Exported OBJ file to: {}".format(obj_file_path))
|
||||
self.report({"INFO"}, "Exported OBJ file to: {}".format(obj_file_path))
|
||||
|
||||
return {'FINISHED'}
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RadianceRender(bpy.types.Operator):
|
||||
"""Radiance Rendering"""
|
||||
|
||||
bl_idname = "render_scene.radiance"
|
||||
bl_label = "Render"
|
||||
bl_description = "Renders the scene using Radiance"
|
||||
|
||||
def execute(self, context):
|
||||
if pr is None:
|
||||
self.report({'ERROR'}, "PyRadiance is not available. Cannot perform rendering.")
|
||||
return {'CANCELLED'}
|
||||
|
||||
self.report({"ERROR"}, "PyRadiance is not available. Cannot perform rendering.")
|
||||
return {"CANCELLED"}
|
||||
|
||||
# Get the resolution from the user input
|
||||
props = context.scene.radiance_exporter_properties
|
||||
resolution_x, resolution_y = props.radiance_resolution_x, props.radiance_resolution_y
|
||||
@@ -138,31 +139,29 @@ class RadianceRender(bpy.types.Operator):
|
||||
|
||||
obj_file_path = os.path.join(output_dir, "model.obj")
|
||||
|
||||
|
||||
camera = self.get_active_camera(context)
|
||||
if camera is None:
|
||||
self.report({'ERROR'}, "No active camera found in the scene. Please add a camera and set it as active.")
|
||||
return {'CANCELLED'}
|
||||
self.report({"ERROR"}, "No active camera found in the scene. Please add a camera and set it as active.")
|
||||
return {"CANCELLED"}
|
||||
|
||||
# Get camera position and direction
|
||||
camera_position, camera_direction = self.get_camera_data(camera)
|
||||
|
||||
# Material processing
|
||||
# style = []
|
||||
|
||||
|
||||
# with open(obj_file_path, "r") as obj_file:
|
||||
# for line in obj_file:
|
||||
# if line.startswith("usemtl"):
|
||||
# l = line.strip().split(" ")
|
||||
# style.append(l[1])
|
||||
|
||||
|
||||
# Check if json file is empty or not
|
||||
props = context.scene.radiance_exporter_properties
|
||||
|
||||
if props.use_json_file:
|
||||
# Load data from JSON file
|
||||
with open(props.json_file, 'r') as file:
|
||||
with open(props.json_file, "r") as file:
|
||||
data = json.load(file)
|
||||
else:
|
||||
# Use in-UI material mappings
|
||||
@@ -170,7 +169,6 @@ class RadianceRender(bpy.types.Operator):
|
||||
|
||||
print(data)
|
||||
|
||||
|
||||
# Create materials.rad file
|
||||
materials_file = os.path.join(output_dir, "materials.rad")
|
||||
with open(materials_file, "w") as file:
|
||||
@@ -190,19 +188,19 @@ class RadianceRender(bpy.types.Operator):
|
||||
# print(i)
|
||||
# file.write("inherit alias " + i + " " + data.get(i, "white") + "\n")
|
||||
|
||||
self.report({'INFO'}, "Exported Materials Rad file to: {}".format(materials_file))
|
||||
self.report({"INFO"}, "Exported Materials Rad file to: {}".format(materials_file))
|
||||
|
||||
# Run obj2mesh
|
||||
rtm_file_path = os.path.join(output_dir, "model.rtm")
|
||||
mesh_file_path = save_obj2mesh_output(obj_file_path, rtm_file_path, matfiles=[materials_file])
|
||||
mesh_file_path = save_obj2mesh_output(obj_file_path, rtm_file_path, matfiles=[materials_file])
|
||||
# subprocess.run(["obj2mesh", "-a", materials_file, obj_file_path, rtm_file_path])
|
||||
self.report({'INFO'}, "obj2mesh output: {}".format(mesh_file_path))
|
||||
self.report({"INFO"}, "obj2mesh output: {}".format(mesh_file_path))
|
||||
scene_file = os.path.join(output_dir, "scene.rad")
|
||||
with open(scene_file, "w") as file:
|
||||
# file.write("void mesh model\n1 " + rtm_file_path + "\n0\n0\n")
|
||||
file.write('void mesh model\n1 "' + rtm_file_path + '"\n0\n0\n')
|
||||
|
||||
self.report({'INFO'}, "Exported Scene file to: {}".format(scene_file))
|
||||
self.report({"INFO"}, "Exported Scene file to: {}".format(scene_file))
|
||||
|
||||
# Py Radiance Rendering code
|
||||
scene = pr.Scene("ascene")
|
||||
@@ -216,26 +214,31 @@ class RadianceRender(bpy.types.Operator):
|
||||
aview = pr.View(position=camera_position, direction=camera_direction)
|
||||
scene.add_view(aview)
|
||||
|
||||
image = pr.render(scene, ambbounce=1, resolution=(resolution_x, resolution_y),
|
||||
quality=quality, detail=detail, variability=variability)
|
||||
|
||||
image = pr.render(
|
||||
scene,
|
||||
ambbounce=1,
|
||||
resolution=(resolution_x, resolution_y),
|
||||
quality=quality,
|
||||
detail=detail,
|
||||
variability=variability,
|
||||
)
|
||||
|
||||
output_path = os.path.join(output_dir, f"{output_file_name}.{output_file_format.lower()}")
|
||||
|
||||
if output_file_format == 'HDR':
|
||||
if output_file_format == "HDR":
|
||||
with open(output_path, "wb") as wtr:
|
||||
wtr.write(image)
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
self.report({'INFO'}, "Radiance rendering completed. Output: {}".format(output_path))
|
||||
return {'FINISHED'}
|
||||
|
||||
self.report({"INFO"}, "Radiance rendering completed. Output: {}".format(output_path))
|
||||
return {"FINISHED"}
|
||||
|
||||
def get_active_camera(self, context):
|
||||
if context.scene.camera:
|
||||
return context.scene.camera
|
||||
for obj in context.scene.objects:
|
||||
if obj.type == 'CAMERA':
|
||||
if obj.type == "CAMERA":
|
||||
return obj
|
||||
return None
|
||||
|
||||
@@ -256,10 +259,11 @@ class RadianceRender(bpy.types.Operator):
|
||||
resolution_y = props.radiance_resolution_y
|
||||
return resolution_x, resolution_y
|
||||
|
||||
|
||||
def save_obj2mesh_output(inp: Union[bytes, str, Path], output_file: str, **kwargs):
|
||||
output_bytes = pr.obj2mesh(inp, **kwargs)
|
||||
|
||||
with open(output_file, 'wb') as f:
|
||||
with open(output_file, "wb") as f:
|
||||
f.write(output_bytes)
|
||||
return output_file
|
||||
|
||||
@@ -333,6 +337,7 @@ class ViewFromSun(bpy.types.Operator):
|
||||
props.hour = props.hour # Just to refresh camera position
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class RefreshIFCMaterials(bpy.types.Operator):
|
||||
bl_idname = "bim.refresh_ifc_materials"
|
||||
bl_label = "Refresh IFC Materials"
|
||||
@@ -341,7 +346,7 @@ class RefreshIFCMaterials(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
props = context.scene.radiance_exporter_properties
|
||||
ifc_file = tool.Ifc.get() if props.should_load_from_memory else ifcopenshell.open(props.ifc_file)
|
||||
|
||||
|
||||
for style in ifc_file.by_type("IfcSurfaceStyle"):
|
||||
for render_item in style.Styles:
|
||||
if render_item.is_a("IfcSurfaceStyleRendering"):
|
||||
@@ -349,5 +354,5 @@ class RefreshIFCMaterials(bpy.types.Operator):
|
||||
style_name = style.Name or f"Unnamed Style {render_item.id()}"
|
||||
if not props.get_material_mapping(style_name):
|
||||
props.add_material_mapping(style_id, style_name)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -170,110 +170,88 @@ class RadianceExporterProperties(PropertyGroup):
|
||||
|
||||
def get_mappings_dict(self):
|
||||
return {item["style_id"]: item["radiance_material"] for item in self.material_mappings}
|
||||
|
||||
|
||||
use_json_file: BoolProperty(
|
||||
name="Upload JSON",
|
||||
description="Toggle between uploading a JSON file and using in-UI material mapping",
|
||||
default=False
|
||||
)
|
||||
|
||||
is_exporting: bpy.props.BoolProperty(
|
||||
name="Is Exporting",
|
||||
description="Whether the OBJ export is in progress",
|
||||
default=False
|
||||
default=False,
|
||||
)
|
||||
|
||||
material_mappings: bpy.props.CollectionProperty(
|
||||
type= bpy.types.PropertyGroup,
|
||||
name="Material Mappings"
|
||||
is_exporting: bpy.props.BoolProperty(
|
||||
name="Is Exporting", description="Whether the OBJ export is in progress", default=False
|
||||
)
|
||||
|
||||
material_mappings: bpy.props.CollectionProperty(type=bpy.types.PropertyGroup, name="Material Mappings")
|
||||
|
||||
should_load_from_memory: BoolProperty(
|
||||
name="Load from Memory",
|
||||
default=False,
|
||||
default=False,
|
||||
)
|
||||
|
||||
radiance_resolution_x: IntProperty(
|
||||
name="X",
|
||||
description="Horizontal resolution of the output image",
|
||||
default=1920,
|
||||
min=1
|
||||
name="X", description="Horizontal resolution of the output image", default=1920, min=1
|
||||
)
|
||||
radiance_resolution_y: IntProperty(
|
||||
name="Y",
|
||||
description="Vertical resolution of the output image",
|
||||
default=1080,
|
||||
min=1
|
||||
name="Y", description="Vertical resolution of the output image", default=1080, min=1
|
||||
)
|
||||
output_dir: StringProperty(
|
||||
name="Output Directory",
|
||||
description="Directory to output Radiance files",
|
||||
default="",
|
||||
subtype="DIR_PATH",
|
||||
update=lambda self, context: self.update_output_dir(context)
|
||||
update=lambda self, context: self.update_output_dir(context),
|
||||
)
|
||||
ifc_file: StringProperty(
|
||||
name="IFC File",
|
||||
description="Path to the IFC file",
|
||||
default="",
|
||||
subtype="FILE_PATH",
|
||||
update=lambda self, context: self.update_ifc_file(context)
|
||||
update=lambda self, context: self.update_ifc_file(context),
|
||||
)
|
||||
json_file: StringProperty(
|
||||
name="JSON File",
|
||||
description="Path to the JSON file",
|
||||
default="",
|
||||
subtype="FILE_PATH",
|
||||
update=lambda self, context: self.update_json_file(context)
|
||||
update=lambda self, context: self.update_json_file(context),
|
||||
)
|
||||
|
||||
|
||||
radiance_quality: EnumProperty(
|
||||
name="Quality",
|
||||
description="Radiance rendering quality",
|
||||
items=[
|
||||
('LOW', "Low", "Low quality"),
|
||||
('MEDIUM', "Medium", "Medium quality"),
|
||||
('HIGH', "High", "High quality")
|
||||
],
|
||||
default='MEDIUM'
|
||||
items=[("LOW", "Low", "Low quality"), ("MEDIUM", "Medium", "Medium quality"), ("HIGH", "High", "High quality")],
|
||||
default="MEDIUM",
|
||||
)
|
||||
radiance_detail: EnumProperty(
|
||||
name="Detail",
|
||||
description="Radiance rendering detail",
|
||||
items=[
|
||||
('LOW', "Low", "Low detail"),
|
||||
('MEDIUM', "Medium", "Medium detail"),
|
||||
('HIGH', "High", "High detail")
|
||||
],
|
||||
default='MEDIUM'
|
||||
items=[("LOW", "Low", "Low detail"), ("MEDIUM", "Medium", "Medium detail"), ("HIGH", "High", "High detail")],
|
||||
default="MEDIUM",
|
||||
)
|
||||
radiance_variability: EnumProperty(
|
||||
name="Variability",
|
||||
description="Radiance rendering variability",
|
||||
items=[
|
||||
('LOW', "Low", "Low variability"),
|
||||
('MEDIUM', "Medium", "Medium variability"),
|
||||
('HIGH', "High", "High variability")
|
||||
("LOW", "Low", "Low variability"),
|
||||
("MEDIUM", "Medium", "Medium variability"),
|
||||
("HIGH", "High", "High variability"),
|
||||
],
|
||||
default="MEDIUM",
|
||||
)
|
||||
output_file_name: StringProperty(
|
||||
name="Output File Name",
|
||||
description="Name of the output image file (without extension)",
|
||||
default="render"
|
||||
name="Output File Name", description="Name of the output image file (without extension)", default="render"
|
||||
)
|
||||
|
||||
|
||||
output_file_format: EnumProperty(
|
||||
name="Output File Format",
|
||||
description="Format of the output image file",
|
||||
items=[
|
||||
('HDR', "HDR", "High Dynamic Range"),
|
||||
("HDR", "HDR", "High Dynamic Range"),
|
||||
],
|
||||
default='HDR'
|
||||
default="HDR",
|
||||
)
|
||||
|
||||
|
||||
|
||||
class BIMSolarProperties(PropertyGroup):
|
||||
sites: EnumProperty(items=get_sites, name="Sites")
|
||||
latitude: FloatProperty(name="Latitude", min=-90, max=90, update=update_latlong)
|
||||
|
||||
@@ -26,11 +26,12 @@ sun_position = tool.Blender.get_sun_position_addon()
|
||||
|
||||
class BIM_PT_radiance_exporter(bpy.types.Panel):
|
||||
"""Creates a Panel in the render properties window"""
|
||||
|
||||
bl_label = "Radiance Exporter"
|
||||
bl_idname = "BIM_PT_radiance_exporter"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_lighting"
|
||||
|
||||
@@ -43,7 +44,7 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
|
||||
if tool.Ifc.get():
|
||||
row = self.layout.row()
|
||||
row.prop(props, "should_load_from_memory")
|
||||
|
||||
|
||||
if not tool.Ifc.get() or not props.should_load_from_memory:
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "ifc_file")
|
||||
@@ -51,7 +52,6 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "output_dir")
|
||||
|
||||
|
||||
row = layout.row()
|
||||
layout.prop(props, "use_json_file")
|
||||
@@ -69,22 +69,21 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
|
||||
|
||||
layout.operator("bim.refresh_ifc_materials")
|
||||
|
||||
|
||||
layout.separator()
|
||||
row = layout.row()
|
||||
row.label(text="Resolution")
|
||||
row.prop(props, "radiance_resolution_x", text="X")
|
||||
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="")
|
||||
row.prop(props, "radiance_resolution_y", text="Y")
|
||||
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "radiance_quality")
|
||||
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "radiance_detail")
|
||||
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "radiance_variability")
|
||||
|
||||
@@ -92,7 +91,7 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "output_file_name")
|
||||
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "output_file_format")
|
||||
layout.separator()
|
||||
@@ -104,12 +103,14 @@ class BIM_PT_radiance_exporter(bpy.types.Panel):
|
||||
row.operator("render_scene.radiance", text="Radiance Render")
|
||||
row.enabled = not props.is_exporting
|
||||
|
||||
|
||||
class BIM_PT_solar(bpy.types.Panel):
|
||||
"""Creates a Panel in the render properties window"""
|
||||
|
||||
bl_label = "Solar Access / Shadow"
|
||||
bl_idname = "BIM_PT_solar"
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_solar_analysis"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
@@ -135,7 +136,7 @@ class BIM_PT_solar(bpy.types.Panel):
|
||||
sun_props = context.scene.sun_pos_properties
|
||||
|
||||
row = self.layout.row()
|
||||
row.prop(sun_props, "coordinates", icon='URL')
|
||||
row.prop(sun_props, "coordinates", icon="URL")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "latitude")
|
||||
row.prop(props, "longitude")
|
||||
@@ -146,20 +147,24 @@ class BIM_PT_solar(bpy.types.Panel):
|
||||
row.operator("bim.import_true_north", icon="IMPORT", text="")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "month", text={
|
||||
1: "January",
|
||||
2: "February",
|
||||
3: "March",
|
||||
4: "April",
|
||||
5: "May",
|
||||
6: "June",
|
||||
7: "July",
|
||||
8: "August",
|
||||
9: "September",
|
||||
10: "October",
|
||||
11: "November",
|
||||
12: "December",
|
||||
}[props.month])
|
||||
row.prop(
|
||||
props,
|
||||
"month",
|
||||
text={
|
||||
1: "January",
|
||||
2: "February",
|
||||
3: "March",
|
||||
4: "April",
|
||||
5: "May",
|
||||
6: "June",
|
||||
7: "July",
|
||||
8: "August",
|
||||
9: "September",
|
||||
10: "October",
|
||||
11: "November",
|
||||
12: "December",
|
||||
}[props.month],
|
||||
)
|
||||
row.prop(props, "day")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
|
||||
@@ -258,7 +258,9 @@ class ObjectMaterialData:
|
||||
precision = bpy.context.scene.DocProperties.imperial_precision
|
||||
else:
|
||||
precision = None
|
||||
formatted_thickness = format_distance(total_thickness, precision=precision, suppress_zero_inches=True, in_unit_length = True)
|
||||
formatted_thickness = format_distance(
|
||||
total_thickness, precision=precision, suppress_zero_inches=True, in_unit_length=True
|
||||
)
|
||||
data["name"] = f"{formatted_thickness} - {data['name']}"
|
||||
if item.is_a("IfcMaterial"):
|
||||
data["material"] = item.Name or "Unnamed"
|
||||
|
||||
@@ -223,7 +223,7 @@ class BIM_PT_object_material(Panel):
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="No Profiles Available")
|
||||
row.operator("bim.add_profile_def", icon="ADD", text="")
|
||||
else:
|
||||
else:
|
||||
row = self.layout.row(align=True)
|
||||
if ObjectMaterialData.data["set_item_name"] == "profile":
|
||||
prop_with_search(row, self.mprops, "profiles", icon="ITALIC", text="")
|
||||
@@ -235,7 +235,10 @@ class BIM_PT_object_material(Panel):
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="----- Exterior -----")
|
||||
for index, set_item in enumerate(ObjectMaterialData.data["set_items"]):
|
||||
if len(self.props.material_set_item_profile_attributes) and self.props.active_material_set_item_id == set_item["id"]:
|
||||
if (
|
||||
len(self.props.material_set_item_profile_attributes)
|
||||
and self.props.active_material_set_item_id == set_item["id"]
|
||||
):
|
||||
self.draw_editable_set_item_profile_ui(set_item)
|
||||
elif self.props.active_material_set_item_id == set_item["id"]:
|
||||
self.draw_editable_set_item_ui(set_item)
|
||||
@@ -341,7 +344,9 @@ class BIM_PT_object_material(Panel):
|
||||
precision = bpy.context.scene.DocProperties.imperial_precision
|
||||
else:
|
||||
precision = None
|
||||
formatted_thickness = format_distance(total_thickness, precision=precision, suppress_zero_inches=True, in_unit_length = True)
|
||||
formatted_thickness = format_distance(
|
||||
total_thickness, precision=precision, suppress_zero_inches=True, in_unit_length=True
|
||||
)
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=f"Total Thickness: {formatted_thickness}")
|
||||
|
||||
|
||||
@@ -84,9 +84,9 @@ class EnableEditingArray(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj = context.active_object
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
props = obj.BIMArrayProperties
|
||||
|
||||
|
||||
relating_obj = props.relating_array_object
|
||||
|
||||
|
||||
if relating_obj:
|
||||
element = tool.Ifc.get_entity(relating_obj)
|
||||
parent_globalid = ifcopenshell.util.element.get_pset(element, "BBIM_Array", "Parent")
|
||||
@@ -102,9 +102,9 @@ class EnableEditingArray(bpy.types.Operator, tool.Ifc.Operator):
|
||||
props.use_local_space = data.get("use_local_space", False)
|
||||
props.sync_children = data.get("sync_children", False)
|
||||
props.method = data.get("method", "OFFSET")
|
||||
|
||||
|
||||
props.is_editing = self.item
|
||||
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -149,9 +149,9 @@ class EditArray(bpy.types.Operator, tool.Ifc.Operator):
|
||||
tool.Blender.Modifier.Array.set_children_lock_state(element, self.item, True)
|
||||
tool.Blender.Modifier.Array.constrain_children_to_parent(element)
|
||||
|
||||
#clears the relating_array_object so it doesn't show again next time
|
||||
# clears the relating_array_object so it doesn't show again next time
|
||||
props.relating_array_object = None
|
||||
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -285,8 +285,11 @@ class SelectAllArrayObjects(bpy.types.Operator):
|
||||
|
||||
array_objects = tool.Blender.Modifier.Array.get_all_objects(parent_element)
|
||||
tool.Blender.set_objects_selection(
|
||||
context, active_object=array_objects[0], selected_objects=array_objects, clear_previous_selection=False
|
||||
)
|
||||
context,
|
||||
active_object=array_objects[0],
|
||||
selected_objects=array_objects,
|
||||
clear_previous_selection=False,
|
||||
)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ class AuthoringData:
|
||||
cls.data["ifc_element_type"] = cls.ifc_element_type
|
||||
cls.data["ifc_classes"] = cls.ifc_classes()
|
||||
cls.data["relating_type_id"] = cls.relating_type_id() # only after .ifc_classes()
|
||||
cls.data["predefined_type"] = cls.predefined_type() # only after .relating_type_id()
|
||||
cls.data["predefined_type"] = cls.predefined_type() # only after .relating_type_id()
|
||||
cls.data["type_class"] = cls.type_class()
|
||||
|
||||
# only after .type_class()
|
||||
|
||||
@@ -541,7 +541,9 @@ class MEPGenerator:
|
||||
ifc_representation_class=None,
|
||||
)
|
||||
|
||||
rel = ifcopenshell.api.run("material.assign_material", ifc_file, products=[element], type="IfcMaterialProfileSet")
|
||||
rel = ifcopenshell.api.run(
|
||||
"material.assign_material", ifc_file, products=[element], type="IfcMaterialProfileSet"
|
||||
)
|
||||
profile_set = rel.RelatingMaterial
|
||||
material_profile = ifcopenshell.api.run(
|
||||
"material.add_profile", ifc_file, profile_set=profile_set, material=material
|
||||
|
||||
@@ -99,9 +99,6 @@ def is_object_array_applicable(self, obj):
|
||||
return ifcopenshell.util.element.get_pset(element, "BBIM_Array")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BIMModelProperties(PropertyGroup):
|
||||
ifc_class: bpy.props.EnumProperty(items=get_ifc_class, name="Construction Class", update=update_ifc_class)
|
||||
relating_type_id: bpy.props.EnumProperty(
|
||||
@@ -226,8 +223,6 @@ class BIMArrayProperties(PropertyGroup):
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
class BIMStairProperties(PropertyGroup):
|
||||
def validate_nosing_value(self, context):
|
||||
if self.stair_type != "WOOD/STEEL" and self.nosing_length < 0:
|
||||
|
||||
@@ -61,10 +61,13 @@ class GenerateSpacesFromWalls(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def msg_no_active_object(self, context):
|
||||
self.layout.label(text="No active object. Please select a wall")
|
||||
|
||||
def msg_no_active_wall(self, context):
|
||||
self.layout.label(text="The active object is not a wall. Please select a wall.")
|
||||
|
||||
def msg_no_container(self, context):
|
||||
self.layout.label(text="The wall is not contained. Please the selected wall in a building container")
|
||||
|
||||
def msg_no_selected_objects(self, context):
|
||||
self.layout.label(text="No selected objects found. Please select walls.")
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ class UpdateDataFromSverchok(bpy.types.Operator, tool.Ifc.Operator):
|
||||
"edges": output_node.inputs["Edges"].sv_get(deepcopy=False, default=[]),
|
||||
"polygons": output_node.inputs["Polygons"].sv_get(deepcopy=False, default=[]),
|
||||
}
|
||||
|
||||
# sv_get returns array of 1 element arrays, for convenience we reduce it to just 1 level array
|
||||
def try_first_element(x):
|
||||
return x[0] if x else x
|
||||
|
||||
@@ -79,7 +79,11 @@ def get_actor_type_enum(self, context):
|
||||
return [
|
||||
("IfcPerson", "Person", get_entity_doc(version, "IfcPerson").get("description", "")),
|
||||
("IfcOrganization", "Organisation", get_entity_doc(version, "IfcOrganization").get("description", "")),
|
||||
("IfcPersonAndOrganization", "User", get_entity_doc(version, "IfcPersonAndOrganization").get("description", "")),
|
||||
(
|
||||
"IfcPersonAndOrganization",
|
||||
"User",
|
||||
get_entity_doc(version, "IfcPersonAndOrganization").get("description", ""),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -127,7 +127,9 @@ class CreateProject(bpy.types.Operator):
|
||||
bpy.data.meshes.remove(mesh)
|
||||
for mat in bpy.data.materials:
|
||||
bpy.data.materials.remove(mat)
|
||||
core.create_project(tool.Ifc, tool.Georeference, tool.Project, tool.Spatial, schema=props.export_schema, template=template)
|
||||
core.create_project(
|
||||
tool.Ifc, tool.Georeference, tool.Project, tool.Spatial, schema=props.export_schema, template=template
|
||||
)
|
||||
blenderbim.bim.schema.reload(tool.Ifc.get().schema_identifier)
|
||||
tool.Blender.register_toolbar()
|
||||
|
||||
|
||||
@@ -170,6 +170,7 @@ def get_group_qto_names(self, context):
|
||||
qtonames[ifc_class] = blender_formatted_enum_from_psets(psets)
|
||||
return qtonames[ifc_class]
|
||||
|
||||
|
||||
def get_profile_pset_names(self, context):
|
||||
global psetnames
|
||||
pprops = context.scene.BIMProfileProperties
|
||||
|
||||
@@ -147,7 +147,7 @@ def draw_psetqto_ui(context, pset_id, pset, props, layout, obj_type, allow_remov
|
||||
row.scale_y = 0.8
|
||||
row.label(text=prop["Name"])
|
||||
op = row.operator("bim.select_similar", text=str(prop["NominalValue"]), icon="NONE", emboss=False)
|
||||
op.key = pset['Name']
|
||||
op.key = pset["Name"]
|
||||
|
||||
if not has_props_displayed:
|
||||
row = box.row()
|
||||
|
||||
@@ -75,7 +75,9 @@ class PsetTemplatesData:
|
||||
pset_dir = os.path.join(bpy.context.scene.BIMProperties.data_dir, "pset")
|
||||
files = os.listdir(pset_dir)
|
||||
for f in files:
|
||||
results.append((os.path.join(pset_dir, f), os.path.splitext(os.path.basename(f))[0], "Global Pset Template"))
|
||||
results.append(
|
||||
(os.path.join(pset_dir, f), os.path.splitext(os.path.basename(f))[0], "Global Pset Template")
|
||||
)
|
||||
|
||||
pset_dir = tool.Ifc.resolve_uri(bpy.context.scene.BIMProperties.pset_dir)
|
||||
if os.path.isdir(pset_dir):
|
||||
|
||||
@@ -350,9 +350,9 @@ class BIM_UL_resources(UIList):
|
||||
"bim.contract_resource", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN"
|
||||
).resource = item.ifc_definition_id
|
||||
else:
|
||||
row.operator(
|
||||
"bim.expand_resource", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT"
|
||||
).resource = item.ifc_definition_id
|
||||
row.operator("bim.expand_resource", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT").resource = (
|
||||
item.ifc_definition_id
|
||||
)
|
||||
else:
|
||||
row.label(text="", icon="DOT")
|
||||
row.prop(item, "name", emboss=False, text="", icon=icon_map[resource["type"]])
|
||||
|
||||
@@ -201,7 +201,10 @@ class IfcClassData:
|
||||
if element:
|
||||
if element.is_a("IfcOpeningElement") or element.is_a("IfcOpeningStandardCase"):
|
||||
return False
|
||||
if element.is_a() in ("IfcWindowStyle", "IfcDoorStyle"): #see https://github.com/IfcOpenShell/IfcOpenShell/issues/4622#issuecomment-2095676368
|
||||
if element.is_a() in (
|
||||
"IfcWindowStyle",
|
||||
"IfcDoorStyle",
|
||||
): # see https://github.com/IfcOpenShell/IfcOpenShell/issues/4622#issuecomment-2095676368
|
||||
return True
|
||||
for product in cls.ifc_products():
|
||||
if element.is_a(product[0]):
|
||||
|
||||
@@ -361,9 +361,7 @@ class SaveColourscheme(Operator, tool.Ifc.Operator):
|
||||
description["colourscheme_query"] = query
|
||||
group.Description = json.dumps(description)
|
||||
else:
|
||||
description = json.dumps(
|
||||
{"type": "BBIM_Search", "colourscheme": colourscheme, "colourscheme_query": query}
|
||||
)
|
||||
description = json.dumps({"type": "BBIM_Search", "colourscheme": colourscheme, "colourscheme_query": query})
|
||||
group = ifcopenshell.api.run("group.add_group", tool.Ifc.get(), name=self.name, description=description)
|
||||
|
||||
def invoke(self, context, event):
|
||||
|
||||
@@ -355,6 +355,7 @@ def update_task_bar_list(self, context):
|
||||
else:
|
||||
tool.Sequence.remove_task_bar(self.ifc_definition_id)
|
||||
|
||||
|
||||
class Task(PropertyGroup):
|
||||
name: StringProperty(name="Name", update=updateTaskName)
|
||||
identification: StringProperty(name="Identification", update=updateTaskIdentification)
|
||||
|
||||
@@ -188,9 +188,9 @@ class BIM_PT_work_schedules(Panel):
|
||||
row1.label(text="Schedule tools")
|
||||
row1 = col.row(align=True)
|
||||
row1.alignment = "RIGHT"
|
||||
row1.operator(
|
||||
"bim.generate_gantt_chart", text="Generate Gantt", icon="NLA"
|
||||
).work_schedule = work_schedule_id
|
||||
row1.operator("bim.generate_gantt_chart", text="Generate Gantt", icon="NLA").work_schedule = (
|
||||
work_schedule_id
|
||||
)
|
||||
row1.operator(
|
||||
"bim.recalculate_schedule", text="Re-calculate Schedule", icon="FILE_REFRESH"
|
||||
).work_schedule = work_schedule_id
|
||||
@@ -226,9 +226,9 @@ class BIM_PT_work_schedules(Panel):
|
||||
)
|
||||
col2 = grid.column()
|
||||
row = col2.row(align=True)
|
||||
row.operator(
|
||||
"bim.enable_editing_work_schedule_tasks", text="Tasks", icon="ACTION"
|
||||
).work_schedule = work_schedule_id
|
||||
row.operator("bim.enable_editing_work_schedule_tasks", text="Tasks", icon="ACTION").work_schedule = (
|
||||
work_schedule_id
|
||||
)
|
||||
row.operator(
|
||||
"bim.enable_editing_work_schedule", text="Attributes", icon="GREASEPENCIL"
|
||||
).work_schedule = work_schedule_id
|
||||
@@ -266,12 +266,12 @@ class BIM_PT_work_schedules(Panel):
|
||||
row2.prop(self.props, "enable_reorder", text="", icon="SORTALPHA")
|
||||
row2.operator("bim.enable_editing_task_sequence", text="", icon="TRACKING")
|
||||
row2.operator("bim.enable_editing_task_time", text="", icon="TIME").task = ifc_definition_id
|
||||
row2.operator(
|
||||
"bim.enable_editing_task_calendar", text="", icon="VIEW_ORTHO"
|
||||
).task = ifc_definition_id
|
||||
row2.operator(
|
||||
"bim.enable_editing_task_attributes", text="", icon="GREASEPENCIL"
|
||||
).task = ifc_definition_id
|
||||
row2.operator("bim.enable_editing_task_calendar", text="", icon="VIEW_ORTHO").task = (
|
||||
ifc_definition_id
|
||||
)
|
||||
row2.operator("bim.enable_editing_task_attributes", text="", icon="GREASEPENCIL").task = (
|
||||
ifc_definition_id
|
||||
)
|
||||
row.operator("bim.add_task", text="Add", icon="ADD").task = ifc_definition_id
|
||||
row.operator("bim.duplicate_task", text="Copy", icon="DUPLICATE").task = ifc_definition_id
|
||||
row.operator("bim.remove_task", text="Delete", icon="X").task = ifc_definition_id
|
||||
@@ -876,13 +876,13 @@ class BIM_UL_tasks(UIList):
|
||||
row.label(text="", icon="BLANK1")
|
||||
if item.has_children:
|
||||
if item.is_expanded:
|
||||
row.operator(
|
||||
"bim.contract_task", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN"
|
||||
).task = item.ifc_definition_id
|
||||
row.operator("bim.contract_task", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN").task = (
|
||||
item.ifc_definition_id
|
||||
)
|
||||
else:
|
||||
row.operator(
|
||||
"bim.expand_task", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT"
|
||||
).task = item.ifc_definition_id
|
||||
row.operator("bim.expand_task", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT").task = (
|
||||
item.ifc_definition_id
|
||||
)
|
||||
else:
|
||||
row.label(text="", icon="DOT")
|
||||
|
||||
|
||||
@@ -59,7 +59,9 @@ def register():
|
||||
bpy.utils.register_tool(workspace.SpatialTool, after={"bim.annotation_tool"}, separator=False, group=False)
|
||||
bpy.types.Scene.BIMSpatialProperties = bpy.props.PointerProperty(type=prop.BIMSpatialProperties)
|
||||
bpy.types.Object.BIMObjectSpatialProperties = bpy.props.PointerProperty(type=prop.BIMObjectSpatialProperties)
|
||||
bpy.types.Scene.BIMSpatialDecompositionProperties = bpy.props.PointerProperty(type=prop.BIMSpatialDecompositionProperties)
|
||||
bpy.types.Scene.BIMSpatialDecompositionProperties = bpy.props.PointerProperty(
|
||||
type=prop.BIMSpatialDecompositionProperties
|
||||
)
|
||||
|
||||
|
||||
def unregister():
|
||||
|
||||
@@ -109,7 +109,7 @@ class BIM_PT_spatial_decomposition(Panel):
|
||||
SpatialDecompositionData.load()
|
||||
self.props = context.scene.BIMSpatialDecompositionProperties
|
||||
|
||||
if SpatialDecompositionData.data['default_container']:
|
||||
if SpatialDecompositionData.data["default_container"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(
|
||||
text=f"Default: {SpatialDecompositionData.data['default_container']}",
|
||||
|
||||
@@ -226,7 +226,7 @@ class StructuralLoadsData:
|
||||
cls.data = {
|
||||
"total_loads": cls.total_loads(),
|
||||
"load_classes": cls.load_classes(),
|
||||
"structural_load_types": cls.structural_load_types()
|
||||
"structural_load_types": cls.structural_load_types(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ def get_applicable_structural_load_types(self, context):
|
||||
|
||||
|
||||
def updateApplicableStructuralLoadTypes(self, context):
|
||||
StructuralLoadCasesData.data[
|
||||
"applicable_structural_load_types"
|
||||
] = StructuralLoadCasesData.applicable_structural_load_types()
|
||||
StructuralLoadCasesData.data["applicable_structural_load_types"] = (
|
||||
StructuralLoadCasesData.applicable_structural_load_types()
|
||||
)
|
||||
|
||||
|
||||
def get_applicable_structural_loads(self, context):
|
||||
|
||||
@@ -388,9 +388,9 @@ class BIM_PT_structural_load_cases(Panel):
|
||||
elif self.props.active_load_case_id:
|
||||
row.operator("bim.remove_structural_load_case", text="", icon="X").load_case = load_case["id"]
|
||||
else:
|
||||
row.operator(
|
||||
"bim.enable_editing_structural_load_case_groups", text="", icon="GHOST_ENABLED"
|
||||
).load_case = load_case["id"]
|
||||
row.operator("bim.enable_editing_structural_load_case_groups", text="", icon="GHOST_ENABLED").load_case = (
|
||||
load_case["id"]
|
||||
)
|
||||
row.operator("bim.enable_editing_structural_load_case", text="", icon="GREASEPENCIL").load_case = load_case[
|
||||
"id"
|
||||
]
|
||||
@@ -547,9 +547,9 @@ class BIM_PT_boundary_conditions(Panel):
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
prop_with_search(row, self.props, "boundary_condition_types", text="")
|
||||
row.operator(
|
||||
"bim.add_boundary_condition", text="", icon="ADD"
|
||||
).ifc_class = self.props.boundary_condition_types
|
||||
row.operator("bim.add_boundary_condition", text="", icon="ADD").ifc_class = (
|
||||
self.props.boundary_condition_types
|
||||
)
|
||||
else:
|
||||
row.operator("bim.load_boundary_conditions", text="", icon="GREASEPENCIL")
|
||||
|
||||
|
||||
@@ -191,9 +191,9 @@ class BIM_PT_ports(Panel):
|
||||
if connected_obj_name:
|
||||
connected_obj = bpy.data.objects[connected_obj_name]
|
||||
cols[3].operator("bim.disconnect_port", text="", icon="UNLINKED").element_id = port.id()
|
||||
cols[4].operator(
|
||||
"bim.select_entity", text="", icon="RESTRICT_SELECT_OFF"
|
||||
).ifc_id = connected_obj.BIMObjectProperties.ifc_definition_id
|
||||
cols[4].operator("bim.select_entity", text="", icon="RESTRICT_SELECT_OFF").ifc_id = (
|
||||
connected_obj.BIMObjectProperties.ifc_definition_id
|
||||
)
|
||||
cols[5].label(text=connected_obj_name)
|
||||
else:
|
||||
cols[3].label(text="", icon="UNLINKED")
|
||||
@@ -248,9 +248,9 @@ class BIM_PT_port(Panel):
|
||||
relating_object = bpy.data.objects[relating_object_name]
|
||||
row.label(text="Port located on:")
|
||||
row.label(text=relating_object_name)
|
||||
row.operator(
|
||||
"bim.select_entity", text="", icon="RESTRICT_SELECT_OFF"
|
||||
).ifc_id = relating_object.BIMObjectProperties.ifc_definition_id
|
||||
row.operator("bim.select_entity", text="", icon="RESTRICT_SELECT_OFF").ifc_id = (
|
||||
relating_object.BIMObjectProperties.ifc_definition_id
|
||||
)
|
||||
|
||||
# object connected to the port
|
||||
row = layout.row(align=True)
|
||||
@@ -259,9 +259,9 @@ class BIM_PT_port(Panel):
|
||||
connected_object = bpy.data.objects[connected_object_name]
|
||||
row.label(text="Port connected to:")
|
||||
row.label(text=connected_object_name)
|
||||
row.operator(
|
||||
"bim.select_entity", text="", icon="RESTRICT_SELECT_OFF"
|
||||
).ifc_id = connected_object.BIMObjectProperties.ifc_definition_id
|
||||
row.operator("bim.select_entity", text="", icon="RESTRICT_SELECT_OFF").ifc_id = (
|
||||
connected_object.BIMObjectProperties.ifc_definition_id
|
||||
)
|
||||
else:
|
||||
row.label(text="Port is not connected to any element")
|
||||
|
||||
@@ -308,9 +308,9 @@ class BIM_PT_flow_controls(Panel):
|
||||
op.flow_control = control_id
|
||||
op.flow_element = flow_element_id
|
||||
op.assign = False
|
||||
row.operator(
|
||||
"bim.select_entity", text="", icon="RESTRICT_SELECT_OFF"
|
||||
).ifc_id = displayed_object.BIMObjectProperties.ifc_definition_id
|
||||
row.operator("bim.select_entity", text="", icon="RESTRICT_SELECT_OFF").ifc_id = (
|
||||
displayed_object.BIMObjectProperties.ifc_definition_id
|
||||
)
|
||||
row.label(text=f"{displayed_object_name}")
|
||||
|
||||
element = tool.Ifc.get_entity(context.active_object)
|
||||
|
||||
@@ -32,7 +32,7 @@ classes = (
|
||||
prop.IfcTesterProperties,
|
||||
ui.BIM_PT_tester,
|
||||
ui.BIM_UL_tester_specifications,
|
||||
ui.BIM_UL_tester_failed_entities
|
||||
ui.BIM_UL_tester_failed_entities,
|
||||
)
|
||||
|
||||
|
||||
@@ -42,4 +42,3 @@ def register():
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.IfcTesterProperties
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ class BIM_PT_tester(Panel):
|
||||
row = box.row(align=True)
|
||||
row.label(text=requirement["description"], icon="CHECKMARK" if requirement["status"] else "CANCEL")
|
||||
if not requirement["status"]:
|
||||
op = row.operator("bim.select_requirement", text="", icon="LONGDISPLAY")
|
||||
op = row.operator("bim.select_requirement", text="", icon="LONGDISPLAY")
|
||||
op2 = row.operator("bim.select_failed_entities", text="", icon="RESTRICT_SELECT_OFF")
|
||||
op.spec_index = props.active_specification_index
|
||||
op.req_index = i
|
||||
|
||||
@@ -88,7 +88,7 @@ class BIM_PT_type(Panel):
|
||||
if TypeData.data["relating_type"]:
|
||||
row.label(text=TypeData.data["relating_type"]["name"])
|
||||
op = row.operator("bim.select_type", icon="OBJECT_DATA", text="")
|
||||
op.relating_type = 0 #will only select the relating types of only the selected objects
|
||||
op.relating_type = 0 # will only select the relating types of only the selected objects
|
||||
row.operator("bim.select_similar_type", icon="RESTRICT_SELECT_OFF", text="")
|
||||
row.operator("bim.enable_editing_type", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.unassign_type", icon="X", text="")
|
||||
|
||||
@@ -141,6 +141,7 @@ class SelectURIAttribute(bpy.types.Operator):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class MultipleFileSelector(bpy.types.Operator):
|
||||
bl_label = "Select Multiple Files"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
@@ -156,11 +157,11 @@ class MultipleFileSelector(bpy.types.Operator):
|
||||
new.name = os.path.join(dirname, f.name)
|
||||
setattr(props, single_file, self.filepath)
|
||||
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class SelectIfcFile(bpy.types.Operator, IFCFileSelector):
|
||||
bl_idname = "bim.select_ifc_file"
|
||||
bl_label = "Select IFC File"
|
||||
|
||||
@@ -45,9 +45,7 @@ def assign_object(
|
||||
relating_object = ifc.get_entity(relating_obj)
|
||||
if aggregator.has_physical_body_representation(relating_object):
|
||||
raise AggregateRepresentationError
|
||||
rel = ifc.run(
|
||||
"aggregate.assign_object", products=[ifc.get_entity(related_obj)], relating_object=relating_object
|
||||
)
|
||||
rel = ifc.run("aggregate.assign_object", products=[ifc.get_entity(related_obj)], relating_object=relating_object)
|
||||
collector.assign(relating_obj)
|
||||
collector.assign(related_obj)
|
||||
aggregator.disable_editing(related_obj)
|
||||
|
||||
@@ -133,7 +133,11 @@ def convert_ifc_to_brick(brick, namespace=None, library=None):
|
||||
for element in distribution_elements:
|
||||
feeds = brick.get_element_feeds(element)
|
||||
for downstream_equipment in feeds:
|
||||
brick.add_relation(equipment_uris[element], "https://brickschema.org/schema/Brick#feeds", equipment_uris[downstream_equipment])
|
||||
brick.add_relation(
|
||||
equipment_uris[element],
|
||||
"https://brickschema.org/schema/Brick#feeds",
|
||||
equipment_uris[downstream_equipment],
|
||||
)
|
||||
brick.run_refresh_brick_viewer()
|
||||
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
# described in regular sentences in under 50 lines. That is the purpose of the
|
||||
# core.
|
||||
|
||||
|
||||
# Here's the simplest possible core function. It does one thing only. Remember:
|
||||
# core functions delegate tasks to tools, so all core functions need at least
|
||||
# one tool.
|
||||
|
||||
@@ -25,7 +25,14 @@ if TYPE_CHECKING:
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
def create_project(ifc: tool.Ifc, georeference: tool.Georeference, project: tool.Project, spatial: tool.Spatial, schema: str, template: Optional[str] = None) -> None:
|
||||
def create_project(
|
||||
ifc: tool.Ifc,
|
||||
georeference: tool.Georeference,
|
||||
project: tool.Project,
|
||||
spatial: tool.Spatial,
|
||||
schema: str,
|
||||
template: Optional[str] = None,
|
||||
) -> None:
|
||||
if ifc.get():
|
||||
return
|
||||
|
||||
|
||||
@@ -149,7 +149,10 @@ class Brick(blenderbim.core.tool.Brick):
|
||||
<{brick_uri}> rdfs:label ?label .
|
||||
}
|
||||
LIMIT 1
|
||||
""".replace("{brick_uri}", brick_uri))
|
||||
""".replace(
|
||||
"{brick_uri}", brick_uri
|
||||
)
|
||||
)
|
||||
name = None
|
||||
for row in query:
|
||||
name = str(row.get("label"))
|
||||
@@ -442,8 +445,6 @@ class Brick(blenderbim.core.tool.Brick):
|
||||
bpy.context.scene.BIMBrickProperties.brick_breadcrumbs.clear()
|
||||
|
||||
|
||||
|
||||
|
||||
class BrickStore:
|
||||
schema = None # this is now a os path
|
||||
path = None # file path if the project was loaded in
|
||||
|
||||
@@ -30,12 +30,14 @@ from math import pi
|
||||
from mathutils import Vector, Matrix
|
||||
from shapely import Polygon, MultiPolygon
|
||||
|
||||
|
||||
class Covering(blenderbim.core.tool.Covering):
|
||||
@classmethod
|
||||
def get_z_from_ceiling_height(cls):
|
||||
props = bpy.context.scene.BIMCoveringProperties
|
||||
return props.ceiling_height
|
||||
|
||||
|
||||
# def toggle_spaces_visibility_wired_and_textured(cls, spaces):
|
||||
# first_obj = tool.Ifc.get_object(spaces[0])
|
||||
# if bpy.data.objects[first_obj.name].display_type == "TEXTURED":
|
||||
|
||||
@@ -13,6 +13,7 @@ try:
|
||||
except ImportError:
|
||||
print("Warning: GitPython not available.")
|
||||
|
||||
|
||||
class IfcGit:
|
||||
@classmethod
|
||||
def init_repo(cls, path_dir):
|
||||
|
||||
@@ -28,6 +28,7 @@ from typing import Optional, Union, Literal
|
||||
|
||||
QuantityTypes = Literal["Q_LENGTH", "Q_AREA", "Q_VOLUME"]
|
||||
|
||||
|
||||
class Qto(blenderbim.core.tool.Qto):
|
||||
@classmethod
|
||||
def get_radius_of_selected_vertices(cls, obj: bpy.types.Object) -> float:
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
@@ -103,7 +104,7 @@ html_theme_options = {
|
||||
"color-link--hover": "#d98014",
|
||||
"color-link--visited--hover": "#d98014",
|
||||
"color-admonition-text": "#651fff",
|
||||
"font-stack": "Nunito, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji"
|
||||
"font-stack": "Nunito, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji",
|
||||
},
|
||||
"dark_css_variables": {
|
||||
"color-brand-primary": "#39b54a",
|
||||
@@ -118,9 +119,8 @@ html_theme_options = {
|
||||
"color-link--hover": "#d98014",
|
||||
"color-link--visited--hover": "#d98014",
|
||||
"color-admonition-text": "#EEEEEC",
|
||||
"font-stack": "Nunito, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji"
|
||||
"font-stack": "Nunito, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji",
|
||||
},
|
||||
|
||||
"footer_icons": [
|
||||
{
|
||||
"name": "IfcOpenShell",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
try:
|
||||
import bpy
|
||||
|
||||
# Ensure it's not fake-bpy-module.
|
||||
if not hasattr(bpy, "context"):
|
||||
raise ModuleNotFoundError
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
import ifcopenshell
|
||||
from brickschema.graph import Graph
|
||||
|
||||
class Generator():
|
||||
|
||||
class Generator:
|
||||
def __init__(self):
|
||||
self.file = ifcopenshell.file(schema='IFC4')
|
||||
self.file = ifcopenshell.file(schema="IFC4")
|
||||
self.schema = Graph()
|
||||
self.schema.load_file("Brick.ttl") # stable 1.3 loaded from external file
|
||||
self.schema.load_file("Brick.ttl") # stable 1.3 loaded from external file
|
||||
|
||||
def generate(self):
|
||||
classification = self.file.create_entity('IfcClassification', **{
|
||||
'Source': 'Brick',
|
||||
'Edition': 'August-11',
|
||||
'EditionDate': '2023-08-11',
|
||||
'Name': 'Brick',
|
||||
'Description': '',
|
||||
'Location': 'https://brickschema.org/schema/Brick',
|
||||
'ReferenceTokens': []
|
||||
})
|
||||
|
||||
classification = self.file.create_entity(
|
||||
"IfcClassification",
|
||||
**{
|
||||
"Source": "Brick",
|
||||
"Edition": "August-11",
|
||||
"EditionDate": "2023-08-11",
|
||||
"Name": "Brick",
|
||||
"Description": "",
|
||||
"Location": "https://brickschema.org/schema/Brick",
|
||||
"ReferenceTokens": [],
|
||||
}
|
||||
)
|
||||
|
||||
query = self.schema.query(
|
||||
"""
|
||||
PREFIX brick: <https://brickschema.org/schema/Brick#>
|
||||
@@ -54,11 +58,11 @@ class Generator():
|
||||
for row in query:
|
||||
# location is the entity URI
|
||||
location = row.get("entity")
|
||||
|
||||
|
||||
# description is the entity's definition
|
||||
description = row.get("definition")
|
||||
if not description:
|
||||
description = ''
|
||||
description = ""
|
||||
|
||||
# name is the entity's label if it exists, else the name in the URI
|
||||
name = row.get("label")
|
||||
@@ -66,13 +70,11 @@ class Generator():
|
||||
name = location.split("#")[-1].replace("_", " ")
|
||||
|
||||
# create the reference
|
||||
ref = self.file.create_entity('IfcClassificationReference', **{
|
||||
'Location': location,
|
||||
'Description': description,
|
||||
'Identification': name,
|
||||
'Name': name
|
||||
})
|
||||
|
||||
ref = self.file.create_entity(
|
||||
"IfcClassificationReference",
|
||||
**{"Location": location, "Description": description, "Identification": name, "Name": name}
|
||||
)
|
||||
|
||||
# get all parents of the entity
|
||||
query = self.schema.query(
|
||||
"""
|
||||
@@ -88,7 +90,7 @@ class Generator():
|
||||
# filter parents for the brick entity
|
||||
for row in query:
|
||||
parent = row.get("parent").toPython()
|
||||
if "brickschema.org" in parent and parent in references.keys():
|
||||
if "brickschema.org" in parent and parent in references.keys():
|
||||
# some parents are not a brick type, so those should be ignored
|
||||
# some entities have multiple parents that are a brick type
|
||||
# since the query traverses down the graph, we can assume at least one parent has been seen, so pick that one
|
||||
@@ -96,7 +98,7 @@ class Generator():
|
||||
break
|
||||
parent = None
|
||||
|
||||
# assign reference source
|
||||
# assign reference source
|
||||
if parent:
|
||||
ref.ReferencedSource = references[parent]
|
||||
else:
|
||||
@@ -105,7 +107,8 @@ class Generator():
|
||||
# save this reference for future reference sources
|
||||
references[location.toPython()] = ref
|
||||
|
||||
self.file.write('Brick.ifc')
|
||||
self.file.write("Brick.ifc")
|
||||
|
||||
|
||||
generator = Generator()
|
||||
generator.generate()
|
||||
generator.generate()
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
import csv
|
||||
import os
|
||||
import json
|
||||
#import pystache
|
||||
|
||||
# import pystache
|
||||
import subprocess
|
||||
import ifcopenshell
|
||||
from pathlib import Path
|
||||
|
||||
class Generator():
|
||||
|
||||
class Generator:
|
||||
def __init__(self):
|
||||
self.file = ifcopenshell.file(schema='IFC4')
|
||||
self.out_dir = './'
|
||||
self.file = ifcopenshell.file(schema="IFC4")
|
||||
self.out_dir = "./"
|
||||
|
||||
def generate(self):
|
||||
classification = self.file.create_entity('IfcClassification', **{
|
||||
'Source': 'VBIS',
|
||||
'Edition': 'May-20',
|
||||
'EditionDate': '2020-05-01',
|
||||
'Name': 'VBIS',
|
||||
'Description': '',
|
||||
'Location': 'https://vbis.com.au/',
|
||||
'ReferenceTokens': ['-']
|
||||
})
|
||||
classification = self.file.create_entity(
|
||||
"IfcClassification",
|
||||
**{
|
||||
"Source": "VBIS",
|
||||
"Edition": "May-20",
|
||||
"EditionDate": "2020-05-01",
|
||||
"Name": "VBIS",
|
||||
"Description": "",
|
||||
"Location": "https://vbis.com.au/",
|
||||
"ReferenceTokens": ["-"],
|
||||
}
|
||||
)
|
||||
# We assume all the Excel spreadsheets are re-exported in CSV format
|
||||
for filename in Path('./').glob('*.csv'):
|
||||
with open(filename, newline='') as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=',', quotechar='"')
|
||||
for filename in Path("./").glob("*.csv"):
|
||||
with open(filename, newline="") as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=",", quotechar='"')
|
||||
name = None
|
||||
levels = [None, None, None, None]
|
||||
ref = classification
|
||||
@@ -39,17 +44,17 @@ class Generator():
|
||||
name = row[2]
|
||||
elif row[3]:
|
||||
name = row[3]
|
||||
ref = self.file.create_entity('IfcClassificationReference', **{
|
||||
'Identification': row[4],
|
||||
'Name': name
|
||||
})
|
||||
cur_level = len(row[4].split('-')) - 1
|
||||
ref = self.file.create_entity(
|
||||
"IfcClassificationReference", **{"Identification": row[4], "Name": name}
|
||||
)
|
||||
cur_level = len(row[4].split("-")) - 1
|
||||
levels[cur_level] = ref
|
||||
if cur_level == 0:
|
||||
ref.ReferencedSource = classification
|
||||
else:
|
||||
ref.ReferencedSource = levels[cur_level-1]
|
||||
self.file.write('VBIS.ifc')
|
||||
ref.ReferencedSource = levels[cur_level - 1]
|
||||
self.file.write("VBIS.ifc")
|
||||
|
||||
|
||||
generator = Generator()
|
||||
generator.generate()
|
||||
|
||||
@@ -7,86 +7,92 @@ import ifcopenshell
|
||||
import ifcopenshell.guid
|
||||
import os
|
||||
|
||||
|
||||
class IFC4Extractor:
|
||||
def __init__(self, xml_file):
|
||||
self.xml_file = xml_file
|
||||
self.tree = ET.parse(self.xml_file)
|
||||
self.root = self.tree.getroot()
|
||||
self.ns = {'xs': 'http://www.w3.org/2001/XMLSchema'}
|
||||
self.ns = {"xs": "http://www.w3.org/2001/XMLSchema"}
|
||||
self.file = ifcopenshell.file()
|
||||
self.data = {
|
||||
'BB/SfB (3/4 cijfers)': {'source': 'Regie der Gebouwen', 'tokens': ['.']},
|
||||
'BIMTypeCode': {'source': 'BIMStockholm', 'tokens': None},
|
||||
'Common Arrangement of Work Sections (CAWS)': {'source': 'NBS', 'tokens': ['/']},
|
||||
'CBI Classification - Level 2': {'source': 'Masterspec', 'tokens': None},
|
||||
'CBI Classification - Level 4': {'source': 'Masterspec', 'tokens': None},
|
||||
'Rumsfunktionskoder CC001 - 001': {'source': 'BIMAlliance', 'tokens': ['-']},
|
||||
'CCS': {'source': 'Molio', 'tokens': None},
|
||||
'CCTB': {'source': 'CCT-Bâtiments', 'tokens': ['.']},
|
||||
'Funktionskoder Regionservice CD001 - 001': {'source': 'BIMAlliance', 'tokens': None},
|
||||
'Rumsfunktion Blekinge CD002 - 001': {'source': 'BIMAlliance', 'tokens': None},
|
||||
'EcoQuaestor Codetabel': {'source': 'EcoQuaestor', 'tokens': ['.', '-']},
|
||||
'GuBIMclass CA': {'source': 'GuBIMClass', 'tokens': ['.']},
|
||||
'GuBIMclass ES': {'source': 'GuBIMClass', 'tokens': ['.']},
|
||||
'MasterFormat': {'source': 'CSI', 'tokens': [' ', '.']},
|
||||
'NATSPEC Worksections': {'source': 'NATSPEC', 'tokens': None},
|
||||
'NBS Create': {'source': 'NBS', 'tokens': ['_', '/']},
|
||||
'NL/SfB (4 cijfers)': {'source': 'BIMLoket', 'tokens': ['.']},
|
||||
'NS 3451 - Bygningsdelstabell': {'source': 'Standard Norge', 'tokens': None},
|
||||
'OmniClass': {'source': 'OmniClass', 'tokens': ['-', ' ']},
|
||||
'ÖNORM 6241-2': {'source': 'freeBIM 2', 'tokens': None},
|
||||
'RICS NRM1': {'source': 'RICS', 'tokens': ['.']},
|
||||
'RICS NRM3': {'source': 'RICS', 'tokens': ['.']},
|
||||
'SFG20': {'source': 'SFG20', 'tokens': ['-']},
|
||||
'SINAPI': {'source': 'Caixa', 'tokens': ['/']},
|
||||
'STABU-Element': {'source': 'STABU', 'tokens': ['.']},
|
||||
'TALO 2000 Building Component Classification': {'source': 'Rakennustieto', 'tokens': ['.']},
|
||||
'TALO 2000 Hankenimikkeistö': {'source': 'Rakennustieto', 'tokens': ['.']},
|
||||
'Uniclass': {'source': 'RIBA Enterprises Ltd', 'tokens': ['_']},
|
||||
'Uniclass 2015': {'source': 'RIBA Enterprises Ltd', 'tokens': ['_']},
|
||||
'UniFormat': {'source': 'UniFormat', 'tokens': ['.']},
|
||||
'Uniformat': {'source': 'UniFormat', 'tokens': ['.']},
|
||||
'VMSW': {'source': 'VMSW', 'tokens': ['.']}
|
||||
"BB/SfB (3/4 cijfers)": {"source": "Regie der Gebouwen", "tokens": ["."]},
|
||||
"BIMTypeCode": {"source": "BIMStockholm", "tokens": None},
|
||||
"Common Arrangement of Work Sections (CAWS)": {"source": "NBS", "tokens": ["/"]},
|
||||
"CBI Classification - Level 2": {"source": "Masterspec", "tokens": None},
|
||||
"CBI Classification - Level 4": {"source": "Masterspec", "tokens": None},
|
||||
"Rumsfunktionskoder CC001 - 001": {"source": "BIMAlliance", "tokens": ["-"]},
|
||||
"CCS": {"source": "Molio", "tokens": None},
|
||||
"CCTB": {"source": "CCT-Bâtiments", "tokens": ["."]},
|
||||
"Funktionskoder Regionservice CD001 - 001": {"source": "BIMAlliance", "tokens": None},
|
||||
"Rumsfunktion Blekinge CD002 - 001": {"source": "BIMAlliance", "tokens": None},
|
||||
"EcoQuaestor Codetabel": {"source": "EcoQuaestor", "tokens": [".", "-"]},
|
||||
"GuBIMclass CA": {"source": "GuBIMClass", "tokens": ["."]},
|
||||
"GuBIMclass ES": {"source": "GuBIMClass", "tokens": ["."]},
|
||||
"MasterFormat": {"source": "CSI", "tokens": [" ", "."]},
|
||||
"NATSPEC Worksections": {"source": "NATSPEC", "tokens": None},
|
||||
"NBS Create": {"source": "NBS", "tokens": ["_", "/"]},
|
||||
"NL/SfB (4 cijfers)": {"source": "BIMLoket", "tokens": ["."]},
|
||||
"NS 3451 - Bygningsdelstabell": {"source": "Standard Norge", "tokens": None},
|
||||
"OmniClass": {"source": "OmniClass", "tokens": ["-", " "]},
|
||||
"ÖNORM 6241-2": {"source": "freeBIM 2", "tokens": None},
|
||||
"RICS NRM1": {"source": "RICS", "tokens": ["."]},
|
||||
"RICS NRM3": {"source": "RICS", "tokens": ["."]},
|
||||
"SFG20": {"source": "SFG20", "tokens": ["-"]},
|
||||
"SINAPI": {"source": "Caixa", "tokens": ["/"]},
|
||||
"STABU-Element": {"source": "STABU", "tokens": ["."]},
|
||||
"TALO 2000 Building Component Classification": {"source": "Rakennustieto", "tokens": ["."]},
|
||||
"TALO 2000 Hankenimikkeistö": {"source": "Rakennustieto", "tokens": ["."]},
|
||||
"Uniclass": {"source": "RIBA Enterprises Ltd", "tokens": ["_"]},
|
||||
"Uniclass 2015": {"source": "RIBA Enterprises Ltd", "tokens": ["_"]},
|
||||
"UniFormat": {"source": "UniFormat", "tokens": ["."]},
|
||||
"Uniformat": {"source": "UniFormat", "tokens": ["."]},
|
||||
"VMSW": {"source": "VMSW", "tokens": ["."]},
|
||||
}
|
||||
|
||||
def extract(self):
|
||||
for system in self.tree.findall('Classification/System'):
|
||||
project = self.file.create_entity('IfcProjectLibrary', Name=system.find('Name').text)
|
||||
parent = self.file.create_entity('IfcClassification', **{
|
||||
'Source': self.data[system.find('Name').text]['source'],
|
||||
'Edition': system.find('EditionVersion').text,
|
||||
'EditionDate': self.get_edition_date(system),
|
||||
'Name': system.find('Name').text,
|
||||
'Description': system.find('Description').text,
|
||||
'Location': system.find('Source').text,
|
||||
'ReferenceTokens': self.data[system.find('Name').text]['tokens']
|
||||
})
|
||||
self.file.createIfcRelAssociatesClassification(
|
||||
ifcopenshell.guid.new(), None, None, None, [project], parent)
|
||||
children = system.findall('Items/Item')
|
||||
for system in self.tree.findall("Classification/System"):
|
||||
project = self.file.create_entity("IfcProjectLibrary", Name=system.find("Name").text)
|
||||
parent = self.file.create_entity(
|
||||
"IfcClassification",
|
||||
**{
|
||||
"Source": self.data[system.find("Name").text]["source"],
|
||||
"Edition": system.find("EditionVersion").text,
|
||||
"EditionDate": self.get_edition_date(system),
|
||||
"Name": system.find("Name").text,
|
||||
"Description": system.find("Description").text,
|
||||
"Location": system.find("Source").text,
|
||||
"ReferenceTokens": self.data[system.find("Name").text]["tokens"],
|
||||
},
|
||||
)
|
||||
self.file.createIfcRelAssociatesClassification(ifcopenshell.guid.new(), None, None, None, [project], parent)
|
||||
children = system.findall("Items/Item")
|
||||
self.get_children(children, parent)
|
||||
|
||||
def get_children(self, children, parent):
|
||||
for child in children:
|
||||
reference = self.file.create_entity('IfcClassificationReference', **{
|
||||
'Identification': child.find('ID').text,
|
||||
'Name': child.find('Name').text,
|
||||
'ReferencedSource': parent,
|
||||
'Description': child.find('Description').text
|
||||
})
|
||||
children = child.find('Children')
|
||||
reference = self.file.create_entity(
|
||||
"IfcClassificationReference",
|
||||
**{
|
||||
"Identification": child.find("ID").text,
|
||||
"Name": child.find("Name").text,
|
||||
"ReferencedSource": parent,
|
||||
"Description": child.find("Description").text,
|
||||
},
|
||||
)
|
||||
children = child.find("Children")
|
||||
if children:
|
||||
self.get_children(children, reference)
|
||||
|
||||
def get_edition_date(self, system):
|
||||
d = system.find('EditionDate')
|
||||
return '{}-{:02}-{:02}'.format(
|
||||
d.find('Year').text, int(d.find('Month').text), int(d.find('Day').text))
|
||||
d = system.find("EditionDate")
|
||||
return "{}-{:02}-{:02}".format(d.find("Year").text, int(d.find("Month").text), int(d.find("Day").text))
|
||||
|
||||
def export(self, filename):
|
||||
self.file.write(filename)
|
||||
|
||||
for filename in os.listdir('xml/'):
|
||||
extractor = IFC4Extractor(f'xml/{filename}')
|
||||
|
||||
for filename in os.listdir("xml/"):
|
||||
extractor = IFC4Extractor(f"xml/{filename}")
|
||||
extractor.extract()
|
||||
extractor.export(f'ifc/{filename[0:-3]}ifc')
|
||||
extractor.export(f"ifc/{filename[0:-3]}ifc")
|
||||
|
||||
@@ -155,10 +155,16 @@ class LibraryGenerator:
|
||||
self.create_line_type("MEDIUM", "medium")
|
||||
self.create_line_type("THICK", "thick")
|
||||
self.create_line_type("STRONG", "strong")
|
||||
self.create_text_type("SETOUT-TAG", "setout-tag", ["E ``round({{easting}}, 0.001)``", "N ``round({{northing}}, 0.001)``"])
|
||||
self.create_text_type(
|
||||
"SETOUT-TAG", "setout-tag", ["E ``round({{easting}}, 0.001)``", "N ``round({{northing}}, 0.001)``"]
|
||||
)
|
||||
self.create_text_type("DOOR-TAG", "door-tag", ["{{type.Name}}", "{{Name}}"])
|
||||
self.create_text_type("WINDOW-TAG", "window-tag", ["{{Name}}"])
|
||||
self.create_text_type("SPACE-TAG", "space-tag", ["{{Name}}", "{{Description}}", "``round({{Qto_SpaceBaseQuantities.NetFloorArea}}, 0.01)``"])
|
||||
self.create_text_type(
|
||||
"SPACE-TAG",
|
||||
"space-tag",
|
||||
["{{Name}}", "{{Description}}", "``round({{Qto_SpaceBaseQuantities.NetFloorArea}}, 0.01)``"],
|
||||
)
|
||||
self.create_text_type("MATERIAL-TAG", "rectangle-tag", ["{{material.Name}}"])
|
||||
self.create_text_type("TYPE-TAG", "capsule-tag", ["{{type.Name}}"])
|
||||
self.create_text_type("NAME-TAG", "capsule-tag", ["{{Name}}"])
|
||||
@@ -189,9 +195,11 @@ class LibraryGenerator:
|
||||
self.file.createIfcDirection((0.0, 0.0, 1.0)),
|
||||
self.file.createIfcDirection((1.0, 0.0, 0.0)),
|
||||
)
|
||||
items.append(self.file.createIfcTextLiteralWithExtent(
|
||||
literal, origin, "RIGHT", self.file.createIfcPlanarExtent(1000, 1000), "center"
|
||||
))
|
||||
items.append(
|
||||
self.file.createIfcTextLiteralWithExtent(
|
||||
literal, origin, "RIGHT", self.file.createIfcPlanarExtent(1000, 1000), "center"
|
||||
)
|
||||
)
|
||||
|
||||
representation = self.file.createIfcShapeRepresentation(
|
||||
self.representations["model_annotation"],
|
||||
@@ -205,22 +213,30 @@ class LibraryGenerator:
|
||||
|
||||
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, products=[element], type="IfcMaterialLayerSet")
|
||||
rel = ifcopenshell.api.run(
|
||||
"material.assign_material", self.file, products=[element], type="IfcMaterialLayerSet"
|
||||
)
|
||||
layer_set = rel.RelatingMaterial
|
||||
layer = ifcopenshell.api.run("material.add_layer", self.file, layer_set=layer_set, material=self.material)
|
||||
layer.LayerThickness = thickness
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[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, products=[element], type="IfcMaterialProfileSet")
|
||||
rel = ifcopenshell.api.run(
|
||||
"material.assign_material", self.file, products=[element], type="IfcMaterialProfileSet"
|
||||
)
|
||||
profile_set = rel.RelatingMaterial
|
||||
material_profile = ifcopenshell.api.run(
|
||||
"material.add_profile", self.file, profile_set=profile_set, material=self.material
|
||||
)
|
||||
ifcopenshell.api.run("material.assign_profile", self.file, material_profile=material_profile, profile=profile)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[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)
|
||||
@@ -252,7 +268,9 @@ class LibraryGenerator:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=element, representation=representation
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[element], relating_context=self.library
|
||||
)
|
||||
|
||||
|
||||
LibraryGenerator().generate()
|
||||
|
||||
@@ -131,7 +131,9 @@ class LibraryGenerator:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=element, representation=representation
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[element], relating_context=self.library
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -244,7 +244,9 @@ class LibraryGenerator:
|
||||
polyline = builder.polyline((V(0, 0), V(width, 0)))
|
||||
_, _, first_semicircle = builder.create_transition_arc_ifc(width, depth, create_ifc_curve=True)
|
||||
|
||||
_, _, second_semicircle = builder.create_transition_arc_ifc(second_arc_width, second_arc_depth, create_ifc_curve=True)
|
||||
_, _, second_semicircle = builder.create_transition_arc_ifc(
|
||||
second_arc_width, second_arc_depth, create_ifc_curve=True
|
||||
)
|
||||
builder.translate(second_semicircle, V((width - second_arc_width) / 2, 0))
|
||||
|
||||
builder.translate([polyline, first_semicircle, second_semicircle], shift_to_center)
|
||||
@@ -934,34 +936,46 @@ class LibraryGenerator:
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
@@ -1130,9 +1144,7 @@ class LibraryGenerator:
|
||||
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,
|
||||
**builder.extrude_kwargs("Y")
|
||||
back_wall, back_wall_depth + back_wall_border_mask_depth, **builder.extrude_kwargs("Y")
|
||||
)
|
||||
items_3d_to_center.append(back_wall_extruded)
|
||||
|
||||
@@ -1202,15 +1214,21 @@ class LibraryGenerator:
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
self.create_explicit_type(
|
||||
"IfcSanitaryTerminalType", "Neufert Large Urinal", representation_3d, representation_2d
|
||||
)
|
||||
|
||||
def create_basin(width, depth, height):
|
||||
second_width = 0.9 * width
|
||||
@@ -1251,19 +1269,27 @@ class LibraryGenerator:
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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
|
||||
@@ -1421,7 +1447,9 @@ class LibraryGenerator:
|
||||
|
||||
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)
|
||||
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)
|
||||
@@ -1442,15 +1470,21 @@ class LibraryGenerator:
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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(
|
||||
@@ -1520,7 +1554,9 @@ class LibraryGenerator:
|
||||
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)
|
||||
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(
|
||||
@@ -1534,7 +1570,9 @@ class LibraryGenerator:
|
||||
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)
|
||||
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)
|
||||
@@ -1670,7 +1708,9 @@ class LibraryGenerator:
|
||||
|
||||
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)
|
||||
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)
|
||||
@@ -1797,13 +1837,17 @@ class LibraryGenerator:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=element, representation=representation_2d
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[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, products=[element], type="IfcMaterialLayerSet")
|
||||
rel = ifcopenshell.api.run(
|
||||
"material.assign_material", self.file, products=[element], type="IfcMaterialLayerSet"
|
||||
)
|
||||
layer_set = rel.RelatingMaterial
|
||||
for layer_data in data["Layers"]:
|
||||
layer = ifcopenshell.api.run(
|
||||
@@ -1811,33 +1855,43 @@ class LibraryGenerator:
|
||||
)
|
||||
layer.Name = layer_data[0]
|
||||
layer.LayerThickness = layer_data[2]
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[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, products=[element], type="IfcMaterialLayerSet")
|
||||
rel = ifcopenshell.api.run(
|
||||
"material.assign_material", self.file, products=[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, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[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, products=[element], type="IfcMaterialProfileSet")
|
||||
rel = ifcopenshell.api.run(
|
||||
"material.assign_material", self.file, products=[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.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, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[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)
|
||||
@@ -1869,7 +1923,9 @@ class LibraryGenerator:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=element, representation=representation
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[element], relating_context=self.library
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -394,9 +394,9 @@ class LibraryGenerator:
|
||||
TreeData("Lollipop Tree (14m)", "simple", (14.0, 7.5, 0.44)),
|
||||
TreeData("Lollipop Tree (18m)", "simple", (18.0, 9.5, 0.44)),
|
||||
TreeData("Lollipop Tree (25m)", "simple", (25.0, 13.5, 0.50)),
|
||||
TreeData("Tree Small (8m)", "low_poly", (8.0, 6.0, 0.0, .8, 1.0, 0.2, 10)),
|
||||
TreeData("Tree Medium (12m)", "low_poly", (12.0, 10.0, 0.0, .8, 2.0, 0.4, 20)),
|
||||
TreeData("Tree Big (20m)", "low_poly", (20.0, 15.0, 0.0, .8, 4.0, 0.6, 30)),
|
||||
TreeData("Tree Small (8m)", "low_poly", (8.0, 6.0, 0.0, 0.8, 1.0, 0.2, 10)),
|
||||
TreeData("Tree Medium (12m)", "low_poly", (12.0, 10.0, 0.0, 0.8, 2.0, 0.4, 20)),
|
||||
TreeData("Tree Big (20m)", "low_poly", (20.0, 15.0, 0.0, 0.8, 4.0, 0.6, 30)),
|
||||
]
|
||||
|
||||
for tree_data in trees:
|
||||
@@ -409,7 +409,7 @@ class LibraryGenerator:
|
||||
|
||||
# From tree species table
|
||||
|
||||
with open(os.path.join(BLEND_DIR, "tree_species.csv"), 'r') as csvfile:
|
||||
with open(os.path.join(BLEND_DIR, "tree_species.csv"), "r") as csvfile:
|
||||
reader = csv.reader(csvfile)
|
||||
for i, row in enumerate(reader):
|
||||
if i == 0:
|
||||
@@ -418,9 +418,7 @@ class LibraryGenerator:
|
||||
data = [float(x) for x in row[2:]]
|
||||
preset_data = preset.preset_class(*data)._asdict()
|
||||
tree_geometry = preset.generator(builder, **preset_data)
|
||||
self.create_explicit_type(
|
||||
"IfcGeographicElementType", row[1], **self.get_representations(tree_geometry)
|
||||
)
|
||||
self.create_explicit_type("IfcGeographicElementType", row[1], **self.get_representations(tree_geometry))
|
||||
|
||||
self.file.write(output_filename)
|
||||
|
||||
@@ -447,7 +445,9 @@ class LibraryGenerator:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=element, representation=representation_2d
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[element], relating_context=self.library
|
||||
)
|
||||
return element
|
||||
|
||||
def create_type(self, ifc_class, name, representations):
|
||||
@@ -480,8 +480,9 @@ class LibraryGenerator:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=element, representation=representation
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[element], relating_context=self.library
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -98,7 +98,9 @@ class LibraryGenerator:
|
||||
ifcopenshell.api.run(
|
||||
"geometry.assign_representation", self.file, product=element, representation=representation
|
||||
)
|
||||
ifcopenshell.api.run("project.assign_declaration", self.file, definitions=[element], relating_context=self.library)
|
||||
ifcopenshell.api.run(
|
||||
"project.assign_declaration", self.file, definitions=[element], relating_context=self.library
|
||||
)
|
||||
|
||||
|
||||
LibraryGenerator().generate()
|
||||
|
||||
@@ -12,12 +12,12 @@ props = bpy.context.scene.BIMGeoreferenceProperties
|
||||
# georeferencing coordinates in the IFC Georeferencing panel before filling out
|
||||
# these details.
|
||||
|
||||
#props.blender_eastings = '334134181.0'
|
||||
#props.blender_northings = '6254570511.0'
|
||||
#props.blender_orthogonal_height = '0.0'
|
||||
#props.blender_x_axis_abscissa = '0.147487884244522'
|
||||
#props.blender_x_axis_ordinate = '0.989063862448262'
|
||||
#props.has_blender_offset = True
|
||||
# props.blender_eastings = '334134181.0'
|
||||
# props.blender_northings = '6254570511.0'
|
||||
# props.blender_orthogonal_height = '0.0'
|
||||
# props.blender_x_axis_abscissa = '0.147487884244522'
|
||||
# props.blender_x_axis_ordinate = '0.989063862448262'
|
||||
# props.has_blender_offset = True
|
||||
|
||||
props = bpy.context.scene.BIMProjectProperties
|
||||
|
||||
|
||||
@@ -40,26 +40,30 @@ if not file:
|
||||
print("No ifc file")
|
||||
sys.exit()
|
||||
|
||||
annotations = file.by_type('IfcAnnotation')
|
||||
annotations = file.by_type("IfcAnnotation")
|
||||
count = 0
|
||||
|
||||
for annotation in annotations:
|
||||
if annotation.ObjectType == 'DRAWING':
|
||||
if annotation.ObjectType == "DRAWING":
|
||||
psets = ifcopenshell.util.element.get_psets(annotation)
|
||||
pset = psets['EPset_Drawing']
|
||||
pset_ifc = file.by_id(pset['id'])
|
||||
pset = psets["EPset_Drawing"]
|
||||
pset_ifc = file.by_id(pset["id"])
|
||||
wrong_sep = ""
|
||||
if platform == 'linux' or platform == 'linux2' or platform == 'darwin':
|
||||
if platform == "linux" or platform == "linux2" or platform == "darwin":
|
||||
wrong_sep = "\\"
|
||||
if platform == 'win32':
|
||||
if platform == "win32":
|
||||
wrong_sep = "/"
|
||||
ifcopenshell.api.run("pset.edit_pset", file, pset = pset_ifc, properties = {
|
||||
'Stylesheet' : pset['Stylesheet'].replace(wrong_sep, os.path.sep),
|
||||
'Markers' : pset['Markers'].replace(wrong_sep, os.path.sep),
|
||||
'Symbols' : pset['Symbols'].replace(wrong_sep, os.path.sep),
|
||||
'Patterns' : pset['Patterns'].replace(wrong_sep, os.path.sep),
|
||||
})
|
||||
count+=1
|
||||
ifcopenshell.api.run(
|
||||
"pset.edit_pset",
|
||||
file,
|
||||
pset=pset_ifc,
|
||||
properties={
|
||||
"Stylesheet": pset["Stylesheet"].replace(wrong_sep, os.path.sep),
|
||||
"Markers": pset["Markers"].replace(wrong_sep, os.path.sep),
|
||||
"Symbols": pset["Symbols"].replace(wrong_sep, os.path.sep),
|
||||
"Patterns": pset["Patterns"].replace(wrong_sep, os.path.sep),
|
||||
},
|
||||
)
|
||||
count += 1
|
||||
|
||||
print(f"DONE! Checked {count} drawings")
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ V = lambda *x: Vector([float(i) for i in x])
|
||||
def simple_uses():
|
||||
ifc_file = ifcopenshell.file()
|
||||
builder = ShapeBuilder(ifc_file)
|
||||
triangle_curve = builder.polyline(( (0., 0.), (1., 2.), (2., 0.) ), closed=True)
|
||||
triangle_curve = builder.polyline(((0.0, 0.0), (1.0, 2.0), (2.0, 0.0)), closed=True)
|
||||
print(triangle_curve)
|
||||
|
||||
rectangle_curve = builder.rectangle()
|
||||
@@ -18,26 +18,19 @@ def simple_uses():
|
||||
circle_curve = builder.circle()
|
||||
print(circle_curve)
|
||||
|
||||
translated_rect = builder.translate(rectangle_curve, Vector( (2.5, 2.5) ), create_copy=True)
|
||||
translated_rect = builder.translate(rectangle_curve, Vector((2.5, 2.5)), create_copy=True)
|
||||
print(translated_rect)
|
||||
|
||||
rotated_triangle = builder.rotate(triangle_curve, 90,
|
||||
pivot_point=Vector( (1., 1.) ),
|
||||
counter_clockwise=True,
|
||||
create_copy=True)
|
||||
rotated_triangle = builder.rotate(
|
||||
triangle_curve, 90, pivot_point=Vector((1.0, 1.0)), counter_clockwise=True, create_copy=True
|
||||
)
|
||||
print(rotated_triangle)
|
||||
|
||||
a, b = builder.translate(
|
||||
[rectangle_curve, circle_curve],
|
||||
Vector( (5., 5.) ), create_copy=True)
|
||||
a, b = builder.translate([rectangle_curve, circle_curve], Vector((5.0, 5.0)), create_copy=True)
|
||||
print(f"Multiple translated objects: {a}, {b}")
|
||||
|
||||
c, d = builder.rotate(
|
||||
[a, b], 90,
|
||||
pivot_point=Vector( (0., 0.) ),
|
||||
counter_clockwise=False,
|
||||
create_copy=True)
|
||||
print(f'Multiple rotated objects: {c}, {d}')
|
||||
c, d = builder.rotate([a, b], 90, pivot_point=Vector((0.0, 0.0)), counter_clockwise=False, create_copy=True)
|
||||
print(f"Multiple rotated objects: {c}, {d}")
|
||||
|
||||
mirrored_objects = builder.mirror(
|
||||
[a, b],
|
||||
@@ -57,8 +50,7 @@ def simple_uses():
|
||||
print(rotated_circle)
|
||||
|
||||
profile = builder.profile(
|
||||
rectangle_curve, "test_profile",
|
||||
inner_curves=[builder.circle(center=Vector((0.5, 0.5)), radius=0.2)]
|
||||
rectangle_curve, "test_profile", inner_curves=[builder.circle(center=Vector((0.5, 0.5)), radius=0.2)]
|
||||
)
|
||||
print(profile)
|
||||
|
||||
@@ -129,20 +121,14 @@ def mirror_placement_test():
|
||||
|
||||
rect_profile = builder.profile(rect, inner_curves=rect_small)
|
||||
|
||||
pl = builder.extrude(rect_profile,
|
||||
magnitude=7.0,
|
||||
position_z_axis=V(0, -1, 0),
|
||||
extrusion_vector=V(0, 0, -1),
|
||||
position=V(0, 5, 0)
|
||||
pl = builder.extrude(
|
||||
rect_profile, magnitude=7.0, position_z_axis=V(0, -1, 0), extrusion_vector=V(0, 0, -1), position=V(0, 5, 0)
|
||||
)
|
||||
|
||||
rect = builder.rectangle(size=size)
|
||||
|
||||
back_wall = builder.extrude(rect,
|
||||
magnitude=2.0,
|
||||
position_z_axis=V(0, -1, 0),
|
||||
extrusion_vector=V(0, 0, -1),
|
||||
position=V(0, 1, 0)
|
||||
back_wall = builder.extrude(
|
||||
rect, magnitude=2.0, position_z_axis=V(0, -1, 0), extrusion_vector=V(0, 0, -1), position=V(0, 1, 0)
|
||||
)
|
||||
|
||||
items_3d = [pl, back_wall]
|
||||
@@ -195,20 +181,18 @@ def curve_between_two_points_test():
|
||||
width, depth = (200.0, 200.0)
|
||||
|
||||
curve_coords = (
|
||||
(V(0, depth), V(-width, 0)), # ccw
|
||||
(V(0, depth), V(width, 0)), # cw
|
||||
(V(0, -depth), V(width, 0)), # ccw
|
||||
(V(0, -depth), V(-width, 0)), # cw
|
||||
|
||||
(V(+width/2, 0), V(0, depth)), # ccw
|
||||
(V(-width/2, 0), V(0, depth)), # cw
|
||||
(V(-width/2, 0), V(0, -depth)), # ccw
|
||||
(V(+width/2, 0), V(0, -depth)), # cw
|
||||
|
||||
(V(0, depth/2), V(+width, 0)), # cw
|
||||
(V(0, depth/2), V(-width, 0)), # ccw
|
||||
(V(0, -depth/2), V(+width, 0)), # ccw
|
||||
(V(0, -depth/2), V(-width, 0)), # cw
|
||||
(V(0, depth), V(-width, 0)), # ccw
|
||||
(V(0, depth), V(width, 0)), # cw
|
||||
(V(0, -depth), V(width, 0)), # ccw
|
||||
(V(0, -depth), V(-width, 0)), # cw
|
||||
(V(+width / 2, 0), V(0, depth)), # ccw
|
||||
(V(-width / 2, 0), V(0, depth)), # cw
|
||||
(V(-width / 2, 0), V(0, -depth)), # ccw
|
||||
(V(+width / 2, 0), V(0, -depth)), # cw
|
||||
(V(0, depth / 2), V(+width, 0)), # cw
|
||||
(V(0, depth / 2), V(-width, 0)), # ccw
|
||||
(V(0, -depth / 2), V(+width, 0)), # ccw
|
||||
(V(0, -depth / 2), V(-width, 0)), # cw
|
||||
)
|
||||
items_2d = [builder.curve_between_two_points(c) for c in curve_coords]
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import multiprocessing
|
||||
|
||||
class BlenderImporter:
|
||||
def __init__(self):
|
||||
self.file = ifcopenshell.open('/home/dion/untitled.ifc')
|
||||
self.file = ifcopenshell.open("/home/dion/untitled.ifc")
|
||||
self.cache_path = "cache.h5"
|
||||
self.should_use_cpu_multiprocessing = True
|
||||
self.deflection_tolerance = 0.001
|
||||
@@ -77,9 +77,7 @@ class BlenderImporter:
|
||||
return results
|
||||
settings = self.settings_2d if is_curve else self.settings
|
||||
if self.should_use_cpu_multiprocessing:
|
||||
iterator = ifcopenshell.geom.iterator(
|
||||
settings, self.file, multiprocessing.cpu_count(), include=products
|
||||
)
|
||||
iterator = ifcopenshell.geom.iterator(settings, self.file, multiprocessing.cpu_count(), include=products)
|
||||
else:
|
||||
iterator = ifcopenshell.geom.iterator(settings, self.file, include=products)
|
||||
cache = self.get_cache()
|
||||
@@ -120,4 +118,5 @@ class BlenderImporter:
|
||||
except:
|
||||
return
|
||||
|
||||
|
||||
BlenderImporter().execute()
|
||||
|
||||
@@ -681,7 +681,7 @@ def prop_is_roughly_value(prop, value):
|
||||
def the_object_name_has_a_cartesian_point_offset_of_offset(name, offset):
|
||||
offset = replace_variables(offset)
|
||||
obj = the_object_name_exists(name)
|
||||
assert obj.BIMObjectProperties.blender_offset_type == "CARTESIAN_POINT"
|
||||
assert obj.BIMObjectProperties.blender_offset_type == "CARTESIAN_POINT"
|
||||
obj_offset = np.array(tuple(map(float, obj.BIMObjectProperties.cartesian_point_offset.split(","))))
|
||||
offset = np.array(tuple(map(float, offset.split(","))))
|
||||
assert np.allclose(obj_offset, offset)
|
||||
|
||||
@@ -159,13 +159,21 @@ class TestAddBrick:
|
||||
brick.run_assign_brick_reference(element="element", library="library", brick_uri="brick_uri").should_be_called()
|
||||
brick.run_refresh_brick_viewer().should_be_called()
|
||||
subject.add_brick(
|
||||
ifc, brick, element="element", namespace="namespace", brick_class="brick_class", library="library", label="label"
|
||||
ifc,
|
||||
brick,
|
||||
element="element",
|
||||
namespace="namespace",
|
||||
brick_class="brick_class",
|
||||
library="library",
|
||||
label="label",
|
||||
)
|
||||
|
||||
def test_adding_a_plain_brick(self, ifc, brick):
|
||||
brick.add_brick("namespace", "brick_class", "label").should_be_called()
|
||||
brick.run_refresh_brick_viewer().should_be_called()
|
||||
subject.add_brick(ifc, brick, element=None, namespace="namespace", brick_class="brick_class", library=None, label="label")
|
||||
subject.add_brick(
|
||||
ifc, brick, element=None, namespace="namespace", brick_class="brick_class", library=None, label="label"
|
||||
)
|
||||
|
||||
|
||||
class TestAddBrickRelation:
|
||||
@@ -197,24 +205,42 @@ class TestConvertIfcToBrick:
|
||||
|
||||
brick.get_convertable_brick_elements().should_be_called().will_return({"element", "downstream_element"})
|
||||
brick.get_brick_class("element").should_be_called().will_return("element_class")
|
||||
brick.add_brick_from_element("element", "namespace", "element_class").should_be_called().will_return("element_uri")
|
||||
brick.add_brick_from_element("element", "namespace", "element_class").should_be_called().will_return(
|
||||
"element_uri"
|
||||
)
|
||||
brick.get_element_container("element").should_be_called().will_return("space")
|
||||
brick.add_relation("element_uri", "https://brickschema.org/schema/Brick#hasLocation", "space_uri").should_be_called()
|
||||
brick.add_relation(
|
||||
"element_uri", "https://brickschema.org/schema/Brick#hasLocation", "space_uri"
|
||||
).should_be_called()
|
||||
brick.get_element_systems("element").should_be_called().will_return(["system"])
|
||||
brick.add_relation("system_uri", "https://brickschema.org/schema/Brick#hasPart", "element_uri").should_be_called()
|
||||
brick.run_assign_brick_reference(element="element", library="library", brick_uri="element_uri").should_be_called()
|
||||
brick.add_relation(
|
||||
"system_uri", "https://brickschema.org/schema/Brick#hasPart", "element_uri"
|
||||
).should_be_called()
|
||||
brick.run_assign_brick_reference(
|
||||
element="element", library="library", brick_uri="element_uri"
|
||||
).should_be_called()
|
||||
|
||||
brick.get_brick_class("downstream_element").should_be_called().will_return("downstream_element_class")
|
||||
brick.add_brick_from_element("downstream_element", "namespace", "downstream_element_class").should_be_called().will_return("downstream_element_uri")
|
||||
brick.add_brick_from_element(
|
||||
"downstream_element", "namespace", "downstream_element_class"
|
||||
).should_be_called().will_return("downstream_element_uri")
|
||||
brick.get_element_container("downstream_element").should_be_called().will_return("space")
|
||||
brick.add_relation("downstream_element_uri", "https://brickschema.org/schema/Brick#hasLocation", "space_uri").should_be_called()
|
||||
brick.add_relation(
|
||||
"downstream_element_uri", "https://brickschema.org/schema/Brick#hasLocation", "space_uri"
|
||||
).should_be_called()
|
||||
brick.get_element_systems("downstream_element").should_be_called().will_return(["system"])
|
||||
brick.add_relation("system_uri", "https://brickschema.org/schema/Brick#hasPart", "downstream_element_uri").should_be_called()
|
||||
brick.run_assign_brick_reference(element="downstream_element", library="library", brick_uri="downstream_element_uri").should_be_called()
|
||||
brick.add_relation(
|
||||
"system_uri", "https://brickschema.org/schema/Brick#hasPart", "downstream_element_uri"
|
||||
).should_be_called()
|
||||
brick.run_assign_brick_reference(
|
||||
element="downstream_element", library="library", brick_uri="downstream_element_uri"
|
||||
).should_be_called()
|
||||
|
||||
brick.get_element_feeds("element").should_be_called().will_return(["downstream_element"])
|
||||
brick.get_element_feeds("downstream_element").should_be_called().will_return([])
|
||||
brick.add_relation("element_uri", "https://brickschema.org/schema/Brick#feeds", "downstream_element_uri").should_be_called()
|
||||
brick.add_relation(
|
||||
"element_uri", "https://brickschema.org/schema/Brick#feeds", "downstream_element_uri"
|
||||
).should_be_called()
|
||||
brick.run_refresh_brick_viewer().should_be_called()
|
||||
subject.convert_ifc_to_brick(brick, namespace="namespace", library="library")
|
||||
|
||||
|
||||
@@ -195,7 +195,9 @@ class TestSwitchRepresentation:
|
||||
geometry.get_object_data("obj").should_be_called().will_return("current_obj_data")
|
||||
geometry.resolve_mapped_representation("mapped_rep").should_be_called().will_return("representation")
|
||||
geometry.get_representation_data("representation").should_be_called().will_return(None)
|
||||
geometry.import_representation("obj", "representation", apply_openings=True).should_be_called().will_return("new_data")
|
||||
geometry.import_representation("obj", "representation", apply_openings=True).should_be_called().will_return(
|
||||
"new_data"
|
||||
)
|
||||
geometry.get_representation_name("representation").should_be_called().will_return("name")
|
||||
geometry.rename_object("new_data", "name").should_be_called()
|
||||
geometry.link("representation", "new_data").should_be_called()
|
||||
@@ -220,7 +222,9 @@ class TestSwitchRepresentation:
|
||||
geometry.get_object_data("obj").should_be_called().will_return("current_obj_data")
|
||||
geometry.resolve_mapped_representation("mapped_rep").should_be_called().will_return("representation")
|
||||
geometry.get_representation_data("representation").should_be_called().will_return("existing_data")
|
||||
geometry.import_representation("obj", "representation", apply_openings=True).should_be_called().will_return("new_data")
|
||||
geometry.import_representation("obj", "representation", apply_openings=True).should_be_called().will_return(
|
||||
"new_data"
|
||||
)
|
||||
geometry.get_representation_name("representation").should_be_called().will_return("name")
|
||||
geometry.rename_object("new_data", "name").should_be_called()
|
||||
geometry.link("representation", "new_data").should_be_called()
|
||||
|
||||
@@ -30,7 +30,9 @@ class TestReferenceStructure:
|
||||
class TestDereferenceStructure:
|
||||
def test_run(self, ifc, spatial):
|
||||
spatial.can_reference("structure", "element").should_be_called().will_return(True)
|
||||
ifc.run("spatial.dereference_structure", products=["element"], relating_structure="structure").should_be_called()
|
||||
ifc.run(
|
||||
"spatial.dereference_structure", products=["element"], relating_structure="structure"
|
||||
).should_be_called()
|
||||
subject.dereference_structure(ifc, spatial, structure="structure", element="element")
|
||||
|
||||
|
||||
|
||||
@@ -26,15 +26,15 @@ class TestAssignSceneUnits:
|
||||
unit.get_scene_unit_si_prefix("LENGTHUNIT").should_be_called().will_return("prefix")
|
||||
unit.get_scene_unit_si_prefix("AREAUNIT").should_be_called().will_return("prefix")
|
||||
unit.get_scene_unit_si_prefix("VOLUMEUNIT").should_be_called().will_return("prefix")
|
||||
ifc.run(
|
||||
"unit.add_si_unit", unit_type="LENGTHUNIT", prefix="prefix"
|
||||
).should_be_called().will_return("lengthunit")
|
||||
ifc.run("unit.add_si_unit", unit_type="LENGTHUNIT", prefix="prefix").should_be_called().will_return(
|
||||
"lengthunit"
|
||||
)
|
||||
|
||||
ifc.run("unit.add_si_unit", unit_type="AREAUNIT", prefix="prefix").should_be_called().will_return("areaunit")
|
||||
|
||||
ifc.run(
|
||||
"unit.add_si_unit", unit_type="VOLUMEUNIT", prefix="prefix"
|
||||
).should_be_called().will_return("volumeunit")
|
||||
ifc.run("unit.add_si_unit", unit_type="VOLUMEUNIT", prefix="prefix").should_be_called().will_return(
|
||||
"volumeunit"
|
||||
)
|
||||
|
||||
ifc.run("unit.add_conversion_based_unit", name="degree").should_be_called().will_return("planeangleunit")
|
||||
|
||||
|
||||
@@ -150,4 +150,3 @@ class TestIsMaterialUsedInSets(NewFile):
|
||||
material_set.MaterialLayers = [material_set_item]
|
||||
material_set_item.Material = material
|
||||
assert subject.is_material_used_in_sets(material) is True
|
||||
|
||||
|
||||
@@ -448,7 +448,9 @@ class TestUsingArrays(NewFile):
|
||||
class TestApplyIfcMaterialChanges(NewFile):
|
||||
def get_used_styles(self, obj: bpy.types.Object) -> set[ifcopenshell.entity_instance]:
|
||||
ifc_file = tool.Ifc.get()
|
||||
return {ifc_file.by_id(s.material.BIMStyleProperties.ifc_definition_id) for s in obj.material_slots if s.material}
|
||||
return {
|
||||
ifc_file.by_id(s.material.BIMStyleProperties.ifc_definition_id) for s in obj.material_slots if s.material
|
||||
}
|
||||
|
||||
def get_mesh(self, obj: bpy.types.Object) -> bpy.types.Mesh:
|
||||
mesh = obj.data
|
||||
|
||||
@@ -104,7 +104,14 @@ class TestSetDefaultContext(NewFile):
|
||||
tool.Ifc.set(ifc)
|
||||
ifc.createIfcProject()
|
||||
model = ifcopenshell.api.run("context.add_context", ifc, context_type="Model")
|
||||
body = ifcopenshell.api.run("context.add_context", ifc, parent=model, context_type="Model", context_identifier="Body", target_view="MODEL_VIEW")
|
||||
body = ifcopenshell.api.run(
|
||||
"context.add_context",
|
||||
ifc,
|
||||
parent=model,
|
||||
context_type="Model",
|
||||
context_identifier="Body",
|
||||
target_view="MODEL_VIEW",
|
||||
)
|
||||
subject.set_default_context()
|
||||
assert bpy.context.scene.BIMRootProperties.contexts == str(body.id())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user