mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 14:02:27 +00:00
RoofData use refactor
This commit is contained in:
@@ -19,11 +19,11 @@
|
|||||||
import bpy
|
import bpy
|
||||||
import math
|
import math
|
||||||
import json
|
import json
|
||||||
import functools
|
|
||||||
import ifcopenshell
|
import ifcopenshell
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
|
from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
|
from math import degrees
|
||||||
|
|
||||||
|
|
||||||
def refresh():
|
def refresh():
|
||||||
@@ -371,26 +371,27 @@ class RailingData:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def pset_data(cls):
|
def pset_data(cls):
|
||||||
return tool.Model.get_railing_pset_data(bpy.context.active_object)
|
return tool.Model.get_modeling_bbim_pset_data(bpy.context.active_object, "BBIM_Railing")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def general_params(cls):
|
def general_params(cls):
|
||||||
props = bpy.context.active_object.BIMRailingProperties
|
props = bpy.context.active_object.BIMRailingProperties
|
||||||
railing_data = cls.data["parameters"]["data_dict"]
|
data = cls.data["parameters"]["data_dict"]
|
||||||
general_params = {}
|
general_params = {}
|
||||||
general_props = props.get_general_kwargs(railing_type=railing_data["railing_type"])
|
general_props = props.get_general_kwargs(railing_type=data["railing_type"])
|
||||||
for prop_name in general_props:
|
for prop_name in general_props:
|
||||||
prop_value = railing_data[prop_name]
|
prop_value = data[prop_name]
|
||||||
prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value
|
prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value
|
||||||
|
|
||||||
prop_readable_name = props.bl_rna.properties[prop_name].name
|
prop_readable_name = props.bl_rna.properties[prop_name].name
|
||||||
general_params[prop_readable_name] = prop_value
|
general_params[prop_readable_name] = prop_value
|
||||||
return general_params
|
return general_params
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def path_data(cls):
|
def path_data(cls):
|
||||||
return cls.data["parameters"]["data_dict"]["path_data"]
|
return cls.data["parameters"]["data_dict"]["path_data"]
|
||||||
|
|
||||||
|
|
||||||
class RoofData:
|
class RoofData:
|
||||||
data = {}
|
data = {}
|
||||||
is_loaded = False
|
is_loaded = False
|
||||||
@@ -398,14 +399,27 @@ class RoofData:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def load(cls):
|
def load(cls):
|
||||||
cls.is_loaded = True
|
cls.is_loaded = True
|
||||||
cls.data = {"parameters": cls.parameters()}
|
cls.data = {}
|
||||||
|
cls.data["parameters"] = cls.pset_data()
|
||||||
|
cls.data["general_params"] = cls.general_params()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parameters(cls):
|
def pset_data(cls):
|
||||||
element = tool.Ifc.get_entity(bpy.context.active_object)
|
return tool.Model.get_modeling_bbim_pset_data(bpy.context.active_object, "BBIM_Roof")
|
||||||
if element:
|
|
||||||
psets = ifcopenshell.util.element.get_psets(element)
|
@classmethod
|
||||||
parameters = psets.get("BBIM_Roof", None)
|
def general_params(cls):
|
||||||
if parameters:
|
props = bpy.context.active_object.BIMRoofProperties
|
||||||
parameters["data_dict"] = json.loads(parameters.get("Data", "[]") or "[]")
|
data = cls.data["parameters"]["data_dict"]
|
||||||
return parameters
|
general_params = {}
|
||||||
|
general_props = props.get_general_kwargs(generation_method=data["generation_method"])
|
||||||
|
for prop_name in general_props:
|
||||||
|
prop_value = data[prop_name]
|
||||||
|
prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value
|
||||||
|
|
||||||
|
if prop_name in ("angle", "rafter_edge_angle"):
|
||||||
|
prop_value = round(degrees(prop_value), 2)
|
||||||
|
|
||||||
|
prop_readable_name = props.bl_rna.properties[prop_name].name
|
||||||
|
general_params[prop_readable_name] = prop_value
|
||||||
|
return general_params
|
||||||
|
|||||||
@@ -629,7 +629,7 @@ class BIMRoofProperties(PropertyGroup):
|
|||||||
("ANGLE", "ANGLE", ""),
|
("ANGLE", "ANGLE", ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
is_editing: bpy.props.IntProperty(default=-1)
|
is_editing: bpy.props.BoolProperty(default=False)
|
||||||
is_editing_path: bpy.props.BoolProperty(default=False)
|
is_editing_path: bpy.props.BoolProperty(default=False)
|
||||||
|
|
||||||
roof_type: bpy.props.EnumProperty(name="Roof Type", items=roof_types, default="HIP/GABLE ROOF")
|
roof_type: bpy.props.EnumProperty(name="Roof Type", items=roof_types, default="HIP/GABLE ROOF")
|
||||||
@@ -643,14 +643,16 @@ class BIMRoofProperties(PropertyGroup):
|
|||||||
roof_thickness: bpy.props.FloatProperty(name="Roof Thickness", default=0.1, subtype="DISTANCE")
|
roof_thickness: bpy.props.FloatProperty(name="Roof Thickness", default=0.1, subtype="DISTANCE")
|
||||||
rafter_edge_angle: bpy.props.FloatProperty(name="Rafter Edge Angle", min=0, max=pi, default=pi / 2, subtype="ANGLE")
|
rafter_edge_angle: bpy.props.FloatProperty(name="Rafter Edge Angle", min=0, max=pi, default=pi / 2, subtype="ANGLE")
|
||||||
|
|
||||||
def get_general_kwargs(self, convert_to_project_units=False):
|
def get_general_kwargs(self, generation_method=None, convert_to_project_units=False):
|
||||||
|
if generation_method is None:
|
||||||
|
generation_method = self.generation_method
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"roof_type": self.roof_type,
|
"roof_type": self.roof_type,
|
||||||
"generation_method": self.generation_method,
|
"generation_method": generation_method,
|
||||||
"roof_thickness": self.roof_thickness,
|
"roof_thickness": self.roof_thickness,
|
||||||
"rafter_edge_angle": self.rafter_edge_angle,
|
"rafter_edge_angle": self.rafter_edge_angle,
|
||||||
}
|
}
|
||||||
if self.generation_method == "HEIGHT":
|
if generation_method == "HEIGHT":
|
||||||
kwargs["height"] = self.height
|
kwargs["height"] = self.height
|
||||||
else:
|
else:
|
||||||
kwargs["angle"] = self.angle
|
kwargs["angle"] = self.angle
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ def update_railing_modifier_ifc_data(context):
|
|||||||
|
|
||||||
if props.railing_type == "WALL_MOUNTED_HANDRAIL":
|
if props.railing_type == "WALL_MOUNTED_HANDRAIL":
|
||||||
body = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
|
body = ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW")
|
||||||
pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object)
|
pset_data = tool.Model.get_modeling_bbim_pset_data(bpy.context.active_object, "BBIM_Railing")
|
||||||
path_data = pset_data["data_dict"]["path_data"]
|
path_data = pset_data["data_dict"]["path_data"]
|
||||||
railing_path = [Vector(v) for v in path_data["verts"]]
|
railing_path = [Vector(v) for v in path_data["verts"]]
|
||||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||||
@@ -117,6 +117,9 @@ def update_bbim_railing_pset(element, railing_data):
|
|||||||
|
|
||||||
|
|
||||||
def update_railing_modifier_bmesh(context):
|
def update_railing_modifier_bmesh(context):
|
||||||
|
"""before using should make sure that Data contains up-to-date information.
|
||||||
|
If BBIM Pset just changed should call refresh() before updating bmesh
|
||||||
|
"""
|
||||||
obj = context.object
|
obj = context.object
|
||||||
props = obj.BIMRailingProperties
|
props = obj.BIMRailingProperties
|
||||||
|
|
||||||
@@ -394,7 +397,7 @@ class FinishEditingRailing(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
props = obj.BIMRailingProperties
|
props = obj.BIMRailingProperties
|
||||||
|
|
||||||
pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object)
|
pset_data = tool.Model.get_modeling_bbim_pset_data(bpy.context.active_object, "BBIM_Railing")
|
||||||
path_data = pset_data["data_dict"]["path_data"]
|
path_data = pset_data["data_dict"]["path_data"]
|
||||||
|
|
||||||
railing_data = props.get_general_kwargs(convert_to_project_units=True)
|
railing_data = props.get_general_kwargs(convert_to_project_units=True)
|
||||||
@@ -417,7 +420,7 @@ class FlipRailingPathOrder(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
props = obj.BIMRailingProperties
|
props = obj.BIMRailingProperties
|
||||||
|
|
||||||
pset_data = tool.Model.get_railing_pset_data(bpy.context.active_object)
|
pset_data = tool.Model.get_modeling_bbim_pset_data(bpy.context.active_object, "BBIM_Railing")
|
||||||
path_data = pset_data["data_dict"]["path_data"]
|
path_data = pset_data["data_dict"]["path_data"]
|
||||||
|
|
||||||
# flip the vertex order and edges
|
# flip the vertex order and edges
|
||||||
|
|||||||
@@ -383,20 +383,6 @@ def bm_get_indices(sequence):
|
|||||||
return [i.index for i in sequence]
|
return [i.index for i in sequence]
|
||||||
|
|
||||||
|
|
||||||
def roof_is_gabled():
|
|
||||||
if not RoofData.is_loaded:
|
|
||||||
RoofData.load()
|
|
||||||
|
|
||||||
path_data = RoofData.parameters()["data_dict"]["path_data"]
|
|
||||||
angle_layer = path_data.get("gable_roof_angles", None)
|
|
||||||
if not angle_layer:
|
|
||||||
return False
|
|
||||||
for edge_angle in angle_layer:
|
|
||||||
if float_is_zero(edge_angle - pi / 2):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def update_roof_modifier_ifc_data(context):
|
def update_roof_modifier_ifc_data(context):
|
||||||
"""should be called after new geometry settled
|
"""should be called after new geometry settled
|
||||||
since it's going to update ifc representation
|
since it's going to update ifc representation
|
||||||
@@ -405,6 +391,17 @@ def update_roof_modifier_ifc_data(context):
|
|||||||
props = obj.BIMRoofProperties
|
props = obj.BIMRoofProperties
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
|
||||||
|
def roof_is_gabled():
|
||||||
|
pset_data = tool.Model.get_modeling_bbim_pset_data(obj, "BBIM_Roof")
|
||||||
|
path_data = pset_data["data_dict"]["path_data"]
|
||||||
|
angle_layer = path_data.get("gable_roof_angles", None)
|
||||||
|
if not angle_layer:
|
||||||
|
return False
|
||||||
|
for edge_angle in angle_layer:
|
||||||
|
if float_is_zero(edge_angle - pi / 2):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
# type attributes
|
# type attributes
|
||||||
if props.roof_type == "HIP/GABLE ROOF":
|
if props.roof_type == "HIP/GABLE ROOF":
|
||||||
element.PredefinedType = "GABLE_ROOF" if roof_is_gabled() else "HIP_ROOF"
|
element.PredefinedType = "GABLE_ROOF" if roof_is_gabled() else "HIP_ROOF"
|
||||||
@@ -424,9 +421,13 @@ def update_bbim_roof_pset(element, roof_data):
|
|||||||
|
|
||||||
|
|
||||||
def update_roof_modifier_bmesh(context):
|
def update_roof_modifier_bmesh(context):
|
||||||
|
"""before using should make sure that Data contains up-to-date information.
|
||||||
|
If BBIM Pset just changed should call refresh() before updating bmesh
|
||||||
|
"""
|
||||||
obj = context.object
|
obj = context.object
|
||||||
props = obj.BIMRoofProperties
|
props = obj.BIMRoofProperties
|
||||||
|
|
||||||
|
# NOTE: using Data since bmesh update will hapen very often
|
||||||
if not RoofData.is_loaded:
|
if not RoofData.is_loaded:
|
||||||
RoofData.load()
|
RoofData.load()
|
||||||
path_data = RoofData.data["parameters"]["data_dict"]["path_data"]
|
path_data = RoofData.data["parameters"]["data_dict"]["path_data"]
|
||||||
@@ -596,7 +597,7 @@ class EnableEditingRoof(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
data = json.loads(ifcopenshell.util.element.get_pset(element, "BBIM_Roof", "Data"))
|
data = json.loads(ifcopenshell.util.element.get_pset(element, "BBIM_Roof", "Data"))
|
||||||
# required since we could load pset from .ifc and BIMRoofProperties won't be set
|
# required since we could load pset from .ifc and BIMRoofProperties won't be set
|
||||||
props.set_props_kwargs_from_ifc_data(data)
|
props.set_props_kwargs_from_ifc_data(data)
|
||||||
props.is_editing = 1
|
props.is_editing = True
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -624,7 +625,7 @@ class CancelEditingRoof(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
should_sync_changes_first=False,
|
should_sync_changes_first=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
props.is_editing = -1
|
props.is_editing = False
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
@@ -638,13 +639,12 @@ class FinishEditingRoof(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
props = obj.BIMRoofProperties
|
props = obj.BIMRoofProperties
|
||||||
|
|
||||||
if not RoofData.is_loaded:
|
pset_data = tool.Model.get_modeling_bbim_pset_data(obj, "BBIM_Roof")
|
||||||
RoofData.load()
|
path_data = pset_data["data_dict"]["path_data"]
|
||||||
path_data = RoofData.data["parameters"]["data_dict"]["path_data"]
|
|
||||||
|
|
||||||
roof_data = props.get_general_kwargs(convert_to_project_units=True)
|
roof_data = props.get_general_kwargs(convert_to_project_units=True)
|
||||||
roof_data["path_data"] = path_data
|
roof_data["path_data"] = path_data
|
||||||
props.is_editing = -1
|
props.is_editing = False
|
||||||
|
|
||||||
update_bbim_roof_pset(element, roof_data)
|
update_bbim_roof_pset(element, roof_data)
|
||||||
update_roof_modifier_ifc_data(context)
|
update_roof_modifier_ifc_data(context)
|
||||||
@@ -769,9 +769,8 @@ class RemoveRoof(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
obj = context.active_object
|
obj = context.active_object
|
||||||
props = obj.BIMRoofProperties
|
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
obj.BIMRoofProperties.is_editing = -1
|
obj.BIMRoofProperties.is_editing = False
|
||||||
|
|
||||||
pset = tool.Pset.get_element_pset(element, "BBIM_Roof")
|
pset = tool.Pset.get_element_pset(element, "BBIM_Roof")
|
||||||
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
ifcopenshell.api.run("pset.remove_pset", tool.Ifc.get(), pset=pset)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import blenderbim.tool as tool
|
import blenderbim.tool as tool
|
||||||
from bpy.types import Panel, Operator, Menu
|
from bpy.types import Panel, Menu
|
||||||
from blenderbim.bim.module.model.data import (
|
from blenderbim.bim.module.model.data import (
|
||||||
AuthoringData,
|
AuthoringData,
|
||||||
ArrayData,
|
ArrayData,
|
||||||
@@ -36,7 +36,6 @@ from blenderbim.bim.module.model.door import update_door_modifier_bmesh
|
|||||||
from blenderbim.bim.module.model.railing import update_railing_modifier_bmesh
|
from blenderbim.bim.module.model.railing import update_railing_modifier_bmesh
|
||||||
from blenderbim.bim.module.model.roof import update_roof_modifier_bmesh
|
from blenderbim.bim.module.model.roof import update_roof_modifier_bmesh
|
||||||
from blenderbim.bim.helper import prop_with_search
|
from blenderbim.bim.helper import prop_with_search
|
||||||
from math import degrees
|
|
||||||
|
|
||||||
|
|
||||||
class LaunchTypeManager(bpy.types.Operator):
|
class LaunchTypeManager(bpy.types.Operator):
|
||||||
@@ -191,7 +190,7 @@ class BIM_PT_array(bpy.types.Panel):
|
|||||||
op.parent = ArrayData.data["parameters"]["Parent"]
|
op.parent = ArrayData.data["parameters"]["Parent"]
|
||||||
op = row.operator("bim.select_all_array_objects", icon="RESTRICT_SELECT_OFF", text="")
|
op = row.operator("bim.select_all_array_objects", icon="RESTRICT_SELECT_OFF", text="")
|
||||||
op.parent = ArrayData.data["parameters"]["Parent"]
|
op.parent = ArrayData.data["parameters"]["Parent"]
|
||||||
|
|
||||||
if ArrayData.data["parameters"]["data_dict"]:
|
if ArrayData.data["parameters"]["data_dict"]:
|
||||||
row.operator("bim.add_array", icon="ADD", text="")
|
row.operator("bim.add_array", icon="ADD", text="")
|
||||||
|
|
||||||
@@ -619,7 +618,7 @@ class BIM_PT_roof(bpy.types.Panel):
|
|||||||
|
|
||||||
roof_data = RoofData.data["parameters"]["data_dict"]
|
roof_data = RoofData.data["parameters"]["data_dict"]
|
||||||
|
|
||||||
if props.is_editing != -1:
|
if props.is_editing:
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.operator("bim.finish_editing_roof", icon="CHECKMARK", text="Finish Editing")
|
row.operator("bim.finish_editing_roof", icon="CHECKMARK", text="Finish Editing")
|
||||||
row.operator("bim.cancel_editing_roof", icon="CANCEL", text="")
|
row.operator("bim.cancel_editing_roof", icon="CANCEL", text="")
|
||||||
@@ -640,14 +639,9 @@ class BIM_PT_roof(bpy.types.Panel):
|
|||||||
row.operator("bim.remove_roof", icon="X", text="")
|
row.operator("bim.remove_roof", icon="X", text="")
|
||||||
|
|
||||||
box = self.layout.box()
|
box = self.layout.box()
|
||||||
general_props = props.get_general_kwargs()
|
for prop_name, prop_value in RoofData.data["general_params"].items():
|
||||||
for prop in general_props:
|
|
||||||
prop_value = roof_data[prop]
|
|
||||||
prop_value = round(prop_value, 5) if type(prop_value) is float else prop_value
|
|
||||||
row = box.row(align=True)
|
row = box.row(align=True)
|
||||||
row.label(text=f"{props.bl_rna.properties[prop].name}")
|
row.label(text=prop_name)
|
||||||
if prop in ("angle", "rafter_edge_angle"):
|
|
||||||
prop_value = round(degrees(prop_value), 2)
|
|
||||||
row.label(text=str(prop_value))
|
row.label(text=str(prop_value))
|
||||||
else:
|
else:
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
|
|||||||
@@ -737,12 +737,13 @@ class Model(blenderbim.core.tool.Model):
|
|||||||
AuthoringData.type_thumbnails[element.id()] = obj.preview.icon_id
|
AuthoringData.type_thumbnails[element.id()] = obj.preview.icon_id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_railing_pset_data(cls, object):
|
def get_modeling_bbim_pset_data(cls, object, pset_name):
|
||||||
|
"""get modelling BBIM pset data (eg, BBIM_Roof) and loads it's `Data` as json to `data_dict`"""
|
||||||
element = tool.Ifc.get_entity(object)
|
element = tool.Ifc.get_entity(object)
|
||||||
if not element:
|
if not element:
|
||||||
return
|
return
|
||||||
psets = ifcopenshell.util.element.get_psets(element)
|
psets = ifcopenshell.util.element.get_psets(element)
|
||||||
pset_data = psets.get("BBIM_Railing", None)
|
pset_data = psets.get(pset_name, None)
|
||||||
if not pset_data:
|
if not pset_data:
|
||||||
return
|
return
|
||||||
pset_data["data_dict"] = json.loads(pset_data.get("Data", "[]") or "[]")
|
pset_data["data_dict"] = json.loads(pset_data.get("Data", "[]") or "[]")
|
||||||
|
|||||||
Reference in New Issue
Block a user