RoofData use refactor

This commit is contained in:
Andrej730
2023-07-13 09:43:37 +05:00
parent a386a14a6f
commit 403c5caf0c
6 changed files with 70 additions and 57 deletions
@@ -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,16 +371,16 @@ 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
@@ -391,6 +391,7 @@ class RailingData:
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):
@@ -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()
+3 -2
View File
@@ -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 "[]")