mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-17 19:09:07 +00:00
typing
This commit is contained in:
@@ -380,7 +380,7 @@ class BIM_PT_object_qtos(Panel):
|
||||
filter_keyword=context.scene.GlobalPsetProperties.qto_filter,
|
||||
)
|
||||
layout = self.layout
|
||||
qtoprops = context.scene.BIMQtoProperties
|
||||
qtoprops = tool.Qto.get_qto_props()
|
||||
row = layout.row(align=True)
|
||||
row.prop(qtoprops, "qto_rule", text="")
|
||||
# A bit confusing as we typically use this icon for is_null.
|
||||
|
||||
@@ -76,6 +76,7 @@ def get_length(o: bpy.types.Object, vg_index: Optional[int] = None) -> float:
|
||||
return max(y, z)
|
||||
|
||||
length = 0
|
||||
assert isinstance(o.data, bpy.types.Mesh)
|
||||
edges = [
|
||||
e
|
||||
for e in o.data.edges
|
||||
@@ -269,6 +270,7 @@ def get_net_perimeter(o: bpy.types.Object) -> float:
|
||||
|
||||
def get_gross_perimeter(o: bpy.types.Object) -> float:
|
||||
element = tool.Ifc.get_entity(o)
|
||||
assert element
|
||||
mesh = get_gross_element_mesh(element)
|
||||
gross_obj = bpy.data.objects.new("GrossObj", mesh)
|
||||
gross_perimeter = get_net_perimeter(gross_obj)
|
||||
@@ -420,6 +422,7 @@ def get_gross_footprint_area(o: bpy.types.Object) -> float:
|
||||
return get_net_footprint_area(o)
|
||||
|
||||
element = tool.Ifc.get_entity(o)
|
||||
assert element
|
||||
mesh = get_gross_element_mesh(element)
|
||||
gross_obj = bpy.data.objects.new("GrossObj", mesh)
|
||||
gross_footprint_area = get_net_footprint_area(gross_obj)
|
||||
@@ -474,6 +477,7 @@ def get_gross_surface_area(o: bpy.types.Object, vg_index: Optional[int] = None)
|
||||
return get_net_surface_area(o)
|
||||
|
||||
element = tool.Ifc.get_entity(o)
|
||||
assert element
|
||||
mesh = get_gross_element_mesh(element)
|
||||
area = get_mesh_area(mesh)
|
||||
bpy.data.meshes.remove(mesh)
|
||||
@@ -506,6 +510,7 @@ def is_polygon_in_vg(polygon: bpy.types.MeshPolygon, vertices_in_vg: list[bpy.ty
|
||||
|
||||
|
||||
def get_net_volume(o: bpy.types.Object) -> float:
|
||||
assert isinstance(o.data, bpy.types.Mesh)
|
||||
o_mesh = bmesh.new()
|
||||
o_mesh.from_mesh(o.data)
|
||||
volume = o_mesh.calc_volume()
|
||||
@@ -518,6 +523,7 @@ def get_gross_volume(o: bpy.types.Object) -> float:
|
||||
return get_net_volume(o)
|
||||
|
||||
element = tool.Ifc.get_entity(o)
|
||||
assert element
|
||||
mesh = get_gross_element_mesh(element)
|
||||
bm = get_bmesh_from_mesh(mesh)
|
||||
|
||||
@@ -562,6 +568,7 @@ def get_net_weight(obj: bpy.types.Object) -> Union[float, None]:
|
||||
|
||||
def get_obj_mass_density(obj: bpy.types.Object) -> Union[float, None]:
|
||||
entity = tool.Ifc.get_entity(obj)
|
||||
assert entity
|
||||
material = ifcopenshell.util.element.get_material(entity)
|
||||
if material is None:
|
||||
return
|
||||
@@ -764,6 +771,7 @@ def get_outer_surface_area(obj: bpy.types.Object) -> float:
|
||||
|
||||
def get_end_area(obj: bpy.types.Object) -> float:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
assert element
|
||||
gross_mesh = get_gross_element_mesh(element)
|
||||
gross_obj = bpy.data.objects.new("MyObject", gross_mesh)
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ def calculate_mesh_quantity(
|
||||
result = 0
|
||||
edit_mode = context.active_object.mode == "EDIT"
|
||||
for obj in objs:
|
||||
assert isinstance(obj.data, bpy.types.Mesh)
|
||||
if edit_mode:
|
||||
bm = bmesh.from_edit_mesh(obj.data)
|
||||
result += operation(bm)
|
||||
|
||||
@@ -49,7 +49,7 @@ class CalculateEdgeLengths(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
result = helper.calculate_edges_lengths([o for o in context.selected_objects if o.type == "MESH"], context)
|
||||
context.scene.BIMQtoProperties.qto_result = str(round(result, 3))
|
||||
tool.Qto.set_qto_result(result)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class CalculateFaceAreas(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
result = helper.calculate_faces_areas([o for o in context.selected_objects if o.type == "MESH"], context)
|
||||
context.scene.BIMQtoProperties.qto_result = str(round(result, 3))
|
||||
tool.Qto.set_qto_result(result)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ class CalculateObjectVolumes(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
result = helper.calculate_volumes([o for o in context.selected_objects if o.type == "MESH"], context)
|
||||
context.scene.BIMQtoProperties.qto_result = str(round(result, 3))
|
||||
tool.Qto.set_qto_result(result)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ class CalculateFormworkArea(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
result = helper.calculate_formwork_area([o for o in context.selected_objects if o.type == "MESH"], context)
|
||||
context.scene.BIMQtoProperties.qto_result = str(round(result, 3))
|
||||
tool.Qto.set_qto_result(result)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ class CalculateSideFormworkArea(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
result = helper.calculate_side_formwork_area([o for o in context.selected_objects if o.type == "MESH"], context)
|
||||
context.scene.BIMQtoProperties.qto_result = str(round(result, 3))
|
||||
tool.Qto.set_qto_result(result)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ class CalculateSingleQuantity(bpy.types.Operator, tool.Ifc.Operator):
|
||||
def _execute(self, context):
|
||||
import ifc5d.qto
|
||||
|
||||
props = context.scene.BIMQtoProperties
|
||||
props = tool.Qto.get_qto_props()
|
||||
elements = set()
|
||||
for obj in tool.Blender.get_selected_objects(include_active=False):
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
@@ -163,7 +163,7 @@ class PerformQuantityTakeOff(bpy.types.Operator, tool.Ifc.Operator):
|
||||
def _execute(self, context):
|
||||
import ifc5d.qto
|
||||
|
||||
props = context.scene.BIMQtoProperties
|
||||
props = tool.Qto.get_qto_props()
|
||||
|
||||
elements: set[ifcopenshell.entity_instance]
|
||||
if context.selected_objects:
|
||||
|
||||
@@ -31,12 +31,16 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
|
||||
def get_qto_rule(self, context):
|
||||
CALCULATOR_FUNCTION_ENUM_ITEMS: list[Union[tuple[str, str, str], None]] = []
|
||||
|
||||
|
||||
def get_qto_rule(self: "BIMQtoProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
|
||||
ifc_file = tool.Ifc.get()
|
||||
is_ifc4x3 = ifc_file.schema == "IFC4X3"
|
||||
results = []
|
||||
results: list[tuple[str, str, str]] = []
|
||||
for rule_id, rule in ifc5d.qto.rules.items():
|
||||
if rule_id.startswith("IFC4X3") != is_ifc4x3:
|
||||
continue
|
||||
@@ -44,14 +48,16 @@ def get_qto_rule(self, context):
|
||||
return results
|
||||
|
||||
|
||||
def get_calculator(self, context):
|
||||
results = []
|
||||
def get_calculator(self: "BIMQtoProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
|
||||
results: list[tuple[str, str, str]] = []
|
||||
for name, calculator in ifc5d.qto.calculators.items():
|
||||
results.append((name, name, calculator.__doc__))
|
||||
results.append((name, name, calculator.__doc__ or ""))
|
||||
return results
|
||||
|
||||
|
||||
def get_calculator_function(self, context):
|
||||
def get_calculator_function(
|
||||
self: "BIMQtoProperties", context: bpy.types.Context
|
||||
) -> list[Union[tuple[str, str, str], None]]:
|
||||
global CALCULATOR_FUNCTION_ENUM_ITEMS
|
||||
calculator = ifc5d.qto.calculators[self.calculator]
|
||||
CALCULATOR_FUNCTION_ENUM_ITEMS = []
|
||||
@@ -60,6 +66,8 @@ def get_calculator_function(self, context):
|
||||
measure = function.measure.split("Measure")[0][3:]
|
||||
if previous_measure is not None and measure != previous_measure:
|
||||
CALCULATOR_FUNCTION_ENUM_ITEMS.append(None)
|
||||
description = function.description
|
||||
description += f"\n\nInternal function id: '{function_id}'."
|
||||
CALCULATOR_FUNCTION_ENUM_ITEMS.append((function_id, f"{measure}: {function.name}", function.description))
|
||||
previous_measure = measure
|
||||
return CALCULATOR_FUNCTION_ENUM_ITEMS
|
||||
@@ -80,3 +88,12 @@ class BIMQtoProperties(PropertyGroup):
|
||||
),
|
||||
default=False,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
qto_rule: str
|
||||
calculator: str
|
||||
calculator_function: str
|
||||
qto_result: str
|
||||
qto_name: str
|
||||
prop_name: str
|
||||
fallback: bool
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.qto.data import QtoData
|
||||
|
||||
|
||||
@@ -32,7 +33,7 @@ class BIM_PT_qto(bpy.types.Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.BIMQtoProperties
|
||||
props = tool.Qto.get_qto_props()
|
||||
|
||||
row = layout.row()
|
||||
if context.selected_objects:
|
||||
@@ -57,7 +58,7 @@ class BIM_PT_qto_manual(bpy.types.Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.BIMQtoProperties
|
||||
props = tool.Qto.get_qto_props()
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "calculator")
|
||||
@@ -83,7 +84,7 @@ class BIM_PT_qto_simple(bpy.types.Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.BIMQtoProperties
|
||||
props = tool.Qto.get_qto_props()
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "qto_result", text="Results")
|
||||
|
||||
@@ -59,7 +59,7 @@ class LoadGroupDecorationData:
|
||||
return ret
|
||||
|
||||
m = models[0]
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
if props.activity_type == "Action":
|
||||
groups = m.LoadedBy or []
|
||||
for g in groups:
|
||||
@@ -128,7 +128,8 @@ class ConnectedStructuralMembersData:
|
||||
if not element:
|
||||
return []
|
||||
results = []
|
||||
props = bpy.context.active_object.BIMStructuralProperties
|
||||
assert obj
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
for rel in element.ConnectsStructuralMembers or []:
|
||||
condition = rel.AppliedCondition
|
||||
if condition:
|
||||
@@ -257,7 +258,7 @@ class StructuralLoadCasesData:
|
||||
|
||||
@classmethod
|
||||
def applicable_structural_loads(cls):
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
results = []
|
||||
for load in tool.Ifc.get().by_type("IfcStructuralLoad"):
|
||||
if not load.Name or not load.is_a(props.applicable_structural_load_types):
|
||||
|
||||
@@ -24,6 +24,7 @@ from mathutils import Vector
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.attribute
|
||||
import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.unit as ifcunit
|
||||
import bonsai.tool as tool
|
||||
from bonsai.bim.module.structural.shader import DecorationShader
|
||||
@@ -304,7 +305,7 @@ class ShaderInfo:
|
||||
populate_members_dict("surface_members", element, activity, factor)
|
||||
recursive_subgroups(subgorups, rec_limit - 1, activity_type, factor=factor)
|
||||
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
group_definition_id = int(props.load_group_to_show)
|
||||
file = tool.Ifc.get()
|
||||
groups = [file.by_id(group_definition_id)]
|
||||
@@ -327,7 +328,7 @@ class ShaderInfo:
|
||||
maximum = max([abs(float(i)) for i in values])
|
||||
if maximum == 0:
|
||||
continue
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
reference_frame = props.reference_frame
|
||||
orientation = np.eye(3)
|
||||
if reference_frame == "LOCAL_COORDS":
|
||||
@@ -435,7 +436,7 @@ class ShaderInfo:
|
||||
) -> np.ndarray:
|
||||
"provides the transformation matrix to convert between reference frames"
|
||||
global_or_local = activity.GlobalOrLocal
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
reference_frame = props.reference_frame
|
||||
transform_matrix = np.eye(3)
|
||||
if reference_frame == "LOCAL_COORDS" and global_or_local != reference_frame:
|
||||
@@ -473,7 +474,7 @@ class ShaderInfo:
|
||||
"mz": (np.array((1, 0, 0)), np.array((0, 1, 0))),
|
||||
}
|
||||
keys = ["fx", "fy", "fz", "mx", "my", "mz"]
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
reference_frame = props.reference_frame
|
||||
if reference_frame == "LOCAL_COORDS":
|
||||
for key in keys:
|
||||
@@ -591,7 +592,7 @@ class ShaderInfo:
|
||||
z_axis = x_axis.cross(y_axis).normalized()
|
||||
rotation = self.get_curve_member_rotation(member)
|
||||
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
reference_frame = props.reference_frame
|
||||
is_local = reference_frame == "LOCAL_COORDS"
|
||||
x_match = abs(Vector((1, 0, 0)).dot(x_axis)) > 0.99
|
||||
|
||||
@@ -20,6 +20,7 @@ import bpy
|
||||
import json
|
||||
import ifcopenshell
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.api.group
|
||||
import ifcopenshell.api.structural
|
||||
import ifcopenshell.util.attribute
|
||||
import bonsai.bim.helper
|
||||
@@ -77,7 +78,7 @@ class AddStructuralMemberConnection(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
oprops = tool.Blender.get_object_bim_props(obj)
|
||||
props = obj.BIMStructuralProperties
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
file = tool.Ifc.get()
|
||||
related_structural_connection = file.by_id(oprops.ifc_definition_id)
|
||||
relating_structural_member = tool.Ifc.get_entity(props.relating_structural_member)
|
||||
@@ -101,7 +102,8 @@ class EnableEditingStructuralConnectionCondition(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMStructuralProperties
|
||||
assert obj
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
props.active_connects_structural_member = self.connects_structural_member
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -113,7 +115,8 @@ class DisableEditingStructuralConnectionCondition(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMStructuralProperties
|
||||
assert obj
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
props.active_connects_structural_member = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -166,7 +169,8 @@ class EnableEditingStructuralBoundaryCondition(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMStructuralProperties
|
||||
assert obj
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
props.boundary_condition_attributes.clear()
|
||||
|
||||
condition = tool.Ifc.get().by_id(self.boundary_condition)
|
||||
@@ -206,7 +210,8 @@ class EditStructuralBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMStructuralProperties
|
||||
assert obj
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
|
||||
file = tool.Ifc.get()
|
||||
connection = file.by_id(self.connection)
|
||||
@@ -236,7 +241,10 @@ class DisableEditingStructuralBoundaryCondition(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.active_object.BIMStructuralProperties.active_boundary_condition = 0
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
props.active_boundary_condition = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -353,7 +361,7 @@ class EnableEditingStructuralItemAxis(bpy.types.Operator):
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
oprops = tool.Blender.get_object_bim_props(obj)
|
||||
props = obj.BIMStructuralProperties
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
|
||||
self.file = tool.Ifc.get()
|
||||
item = self.file.by_id(oprops.ifc_definition_id)
|
||||
@@ -392,7 +400,8 @@ class DisableEditingStructuralItemAxis(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMStructuralProperties
|
||||
assert obj
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
props.is_editing_axis = False
|
||||
if props.axis_empty:
|
||||
bpy.data.objects.remove(props.axis_empty)
|
||||
@@ -407,7 +416,7 @@ class EditStructuralItemAxis(bpy.types.Operator, tool.Ifc.Operator):
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
oprops = tool.Blender.get_object_bim_props(obj)
|
||||
props = obj.BIMStructuralProperties
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
relative_matrix = props.axis_empty.matrix_world @ obj.matrix_world.inverted()
|
||||
z_axis = relative_matrix.col[2][0:3]
|
||||
self.file = tool.Ifc.get()
|
||||
@@ -429,7 +438,7 @@ class EnableEditingStructuralConnectionCS(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
props = obj.BIMStructuralProperties
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
|
||||
self.file = tool.Ifc.get()
|
||||
item = tool.Ifc.get_entity(obj)
|
||||
@@ -481,7 +490,8 @@ class DisableEditingStructuralConnectionCS(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMStructuralProperties
|
||||
assert obj
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
props.is_editing_connection_cs = False
|
||||
if props.ccs_empty:
|
||||
bpy.data.objects.remove(props.ccs_empty)
|
||||
@@ -498,7 +508,7 @@ class EditStructuralConnectionCS(bpy.types.Operator, tool.Ifc.Operator):
|
||||
assert obj
|
||||
item = tool.Ifc.get_entity(obj)
|
||||
assert item
|
||||
props = obj.BIMStructuralProperties
|
||||
props = tool.Structural.get_object_structural_props(obj)
|
||||
relative_matrix = props.ccs_empty.matrix_world @ obj.matrix_world.inverted()
|
||||
x_axis = relative_matrix.col[0][0:3]
|
||||
z_axis = relative_matrix.col[2][0:3]
|
||||
@@ -567,13 +577,13 @@ class EditStructuralLoadCase(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
attributes = bonsai.bim.helper.export_attributes(props.load_case_attributes)
|
||||
self.file = tool.Ifc.get()
|
||||
ifcopenshell.api.run(
|
||||
"structural.edit_structural_load_case",
|
||||
ifcopenshell.api.structural.edit_structural_load_case(
|
||||
self.file,
|
||||
**{"load_case": self.file.by_id(props.active_load_case_id), "attributes": attributes},
|
||||
load_case=self.file.by_id(props.active_load_case_id),
|
||||
attributes=attributes,
|
||||
)
|
||||
bpy.ops.bim.disable_editing_structural_load_case()
|
||||
return {"FINISHED"}
|
||||
@@ -587,9 +597,7 @@ class RemoveStructuralLoadCase(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = tool.Ifc.get()
|
||||
ifcopenshell.api.run(
|
||||
"structural.remove_structural_load_case", self.file, load_case=self.file.by_id(self.load_case)
|
||||
)
|
||||
ifcopenshell.api.structural.remove_structural_load_case(self.file, load_case=self.file.by_id(self.load_case))
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -600,7 +608,7 @@ class EnableEditingStructuralLoadCase(bpy.types.Operator):
|
||||
load_case: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props = tool.Structural.get_structural_props()
|
||||
self.props.active_load_case_id = self.load_case
|
||||
self.props.load_case_editing_type = "ATTRIBUTES"
|
||||
self.props.load_case_attributes.clear()
|
||||
@@ -620,7 +628,8 @@ class DisableEditingStructuralLoadCase(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMStructuralProperties.active_load_case_id = 0
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.active_load_case_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -631,9 +640,9 @@ class EnableEditingStructuralLoadCaseGroups(bpy.types.Operator):
|
||||
load_case: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props.active_load_case_id = self.load_case
|
||||
self.props.load_case_editing_type = "GROUPS"
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.active_load_case_id = self.load_case
|
||||
props.load_case_editing_type = "GROUPS"
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -645,10 +654,8 @@ class AddStructuralLoadGroup(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = tool.Ifc.get()
|
||||
load_group = ifcopenshell.api.run("structural.add_structural_load_group", self.file)
|
||||
ifcopenshell.api.run(
|
||||
"group.assign_group", self.file, products=[load_group], group=self.file.by_id(self.load_case)
|
||||
)
|
||||
load_group = ifcopenshell.api.structural.add_structural_load_group(self.file)
|
||||
ifcopenshell.api.group.assign_group(self.file, products=[load_group], group=self.file.by_id(self.load_case))
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -660,9 +667,7 @@ class RemoveStructuralLoadGroup(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
self.file = tool.Ifc.get()
|
||||
ifcopenshell.api.run(
|
||||
"structural.remove_structural_load_group", self.file, load_group=self.file.by_id(self.load_group)
|
||||
)
|
||||
ifcopenshell.api.structural.remove_structural_load_group(self.file, load_group=self.file.by_id(self.load_group))
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -674,15 +679,15 @@ class EnableEditingStructuralLoadGroupActivities(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
self.file = tool.Ifc.get()
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props = tool.Structural.get_structural_props()
|
||||
self.props.active_load_group_id = self.load_group
|
||||
self.props.load_group_editing_type = "ACTIVITY"
|
||||
self.load_structural_activities()
|
||||
return {"FINISHED"}
|
||||
|
||||
def load_structural_activities(self):
|
||||
def load_structural_activities(self) -> None:
|
||||
self.props.load_group_activities.clear()
|
||||
for rel in tool.Ifc.get().by_id(self.load_group).IsGroupedBy:
|
||||
for rel in self.file.by_id(self.load_group).IsGroupedBy:
|
||||
for activity in rel.RelatedObjects:
|
||||
new = self.props.load_group_activities.add()
|
||||
new.ifc_definition_id = activity.id()
|
||||
@@ -697,7 +702,7 @@ class AddStructuralActivity(bpy.types.Operator, tool.Ifc.Operator):
|
||||
load_group: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props = tool.Structural.get_structural_props()
|
||||
self.file = tool.Ifc.get()
|
||||
for obj in context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
@@ -726,16 +731,13 @@ class AddStructuralActivity(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
ifc_class = applicable_activity_class[element.is_a()]
|
||||
|
||||
activity = ifcopenshell.api.run(
|
||||
"structural.add_structural_activity",
|
||||
activity = ifcopenshell.api.structural.add_structural_activity(
|
||||
self.file,
|
||||
ifc_class=ifc_class,
|
||||
applied_load=self.file.by_id(int(self.props.applicable_structural_loads)),
|
||||
structural_member=element,
|
||||
)
|
||||
ifcopenshell.api.run(
|
||||
"group.assign_group", self.file, products=[activity], group=self.file.by_id(self.load_group)
|
||||
)
|
||||
ifcopenshell.api.group.assign_group(self.file, products=[activity], group=self.file.by_id(self.load_group))
|
||||
bpy.ops.bim.enable_editing_structural_load_group_activities(load_group=self.load_group)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -747,7 +749,7 @@ class LoadStructuralLoads(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
self.file = tool.Ifc.get()
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.structural_loads.clear()
|
||||
loads = tool.Ifc.get().by_type("IfcStructuralLoad")
|
||||
if props.filtered_structural_loads:
|
||||
@@ -780,7 +782,8 @@ class DisableStructuralLoadEditingUI(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMStructuralProperties.is_editing_loads = False
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.is_editing_loads = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -806,7 +809,7 @@ class EnableEditingStructuralLoad(bpy.types.Operator):
|
||||
structural_load: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.structural_load_attributes.clear()
|
||||
bonsai.bim.helper.import_attributes2(
|
||||
tool.Ifc.get().by_id(self.structural_load), props.structural_load_attributes
|
||||
@@ -821,7 +824,8 @@ class DisableEditingStructuralLoad(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMStructuralProperties.active_structural_load_id = 0
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.active_structural_load_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -832,12 +836,10 @@ class RemoveStructuralLoad(bpy.types.Operator, tool.Ifc.Operator):
|
||||
structural_load: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
self.file = tool.Ifc.get()
|
||||
ifcopenshell.api.run(
|
||||
"structural.remove_structural_load",
|
||||
ifcopenshell.api.structural.remove_structural_load(
|
||||
self.file,
|
||||
**{"structural_load": self.file.by_id(self.structural_load)},
|
||||
structural_load=self.file.by_id(self.structural_load),
|
||||
)
|
||||
bpy.ops.bim.load_structural_loads()
|
||||
return {"FINISHED"}
|
||||
@@ -849,16 +851,13 @@ class EditStructuralLoad(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
attributes = bonsai.bim.helper.export_attributes(props.structural_load_attributes)
|
||||
self.file = tool.Ifc.get()
|
||||
ifcopenshell.api.run(
|
||||
"structural.edit_structural_load",
|
||||
ifcopenshell.api.structural.edit_structural_load(
|
||||
self.file,
|
||||
**{
|
||||
"structural_load": self.file.by_id(props.active_structural_load_id),
|
||||
"attributes": attributes,
|
||||
},
|
||||
structural_load=self.file.by_id(props.active_structural_load_id),
|
||||
attributes=attributes,
|
||||
)
|
||||
bpy.ops.bim.load_structural_loads()
|
||||
return {"FINISHED"}
|
||||
@@ -870,7 +869,7 @@ class ToggleFilterStructuralLoads(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.filtered_structural_loads = not props.filtered_structural_loads
|
||||
bpy.ops.bim.load_structural_loads()
|
||||
return {"FINISHED"}
|
||||
@@ -883,7 +882,7 @@ class LoadBoundaryConditions(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
self.file = tool.Ifc.get()
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.boundary_conditions.clear()
|
||||
conditions = tool.Ifc.get().by_type("IfcBoundaryCondition")
|
||||
if props.filtered_boundary_conditions:
|
||||
@@ -916,7 +915,7 @@ class ToggleFilterBoundaryConditions(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.filtered_boundary_conditions = not props.filtered_boundary_conditions
|
||||
bpy.ops.bim.load_boundary_conditions()
|
||||
return {"FINISHED"}
|
||||
@@ -928,7 +927,8 @@ class DisableBoundaryConditionEditingUI(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMStructuralProperties.is_editing_boundary_conditions = False
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.is_editing_boundary_conditions = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -939,8 +939,7 @@ class AddBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
|
||||
ifc_class: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
result = ifcopenshell.api.run(
|
||||
"structural.add_structural_boundary_condition",
|
||||
result = ifcopenshell.api.structural.add_structural_boundary_condition(
|
||||
tool.Ifc.get(),
|
||||
name="New Load",
|
||||
ifc_class=self.ifc_class,
|
||||
@@ -957,7 +956,7 @@ class EnableEditingBoundaryCondition(bpy.types.Operator):
|
||||
boundary_condition: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.boundary_condition_attributes.clear()
|
||||
|
||||
boundary_condition = tool.Ifc.get().by_id(self.boundary_condition)
|
||||
@@ -994,7 +993,8 @@ class DisableEditingBoundaryCondition(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BIMStructuralProperties.active_boundary_condition_id = 0
|
||||
props = tool.Structural.get_structural_props()
|
||||
props.active_boundary_condition_id = 0
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -1005,12 +1005,10 @@ class RemoveBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
|
||||
boundary_condition: bpy.props.IntProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
self.file = tool.Ifc.get()
|
||||
ifcopenshell.api.run(
|
||||
"structural.remove_structural_boundary_condition",
|
||||
ifcopenshell.api.structural.remove_structural_boundary_condition(
|
||||
self.file,
|
||||
**{"boundary_condition": self.file.by_id(self.boundary_condition)},
|
||||
boundary_condition=self.file.by_id(self.boundary_condition),
|
||||
)
|
||||
bpy.ops.bim.load_boundary_conditions()
|
||||
return {"FINISHED"}
|
||||
@@ -1022,7 +1020,7 @@ class EditBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMStructuralProperties
|
||||
props = tool.Structural.get_structural_props()
|
||||
self.file = tool.Ifc.get()
|
||||
# attributes = bonsai.bim.helper.export_attributes(props.boundary_condition_attributes)
|
||||
attributes = {}
|
||||
@@ -1035,10 +1033,10 @@ class EditBoundaryCondition(bpy.types.Operator, tool.Ifc.Operator):
|
||||
attributes[attribute.name] = {"value": attribute.bool_value, "type": attribute.enum_value}
|
||||
else:
|
||||
attributes[attribute.name] = {"value": attribute.float_value, "type": attribute.enum_value}
|
||||
ifcopenshell.api.run(
|
||||
"structural.edit_structural_boundary_condition",
|
||||
ifcopenshell.api.structural.edit_structural_boundary_condition(
|
||||
self.file,
|
||||
**{"condition": self.file.by_id(props.active_boundary_condition_id), "attributes": attributes},
|
||||
condition=self.file.by_id(props.active_boundary_condition_id),
|
||||
attributes=attributes,
|
||||
)
|
||||
bpy.ops.bim.load_boundary_conditions()
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -37,52 +37,62 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
|
||||
def get_load_groups_to_show(self, context):
|
||||
def get_load_groups_to_show(self: "BIMStructuralProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
|
||||
if not LoadGroupDecorationData.is_loaded:
|
||||
LoadGroupDecorationData.load()
|
||||
return LoadGroupDecorationData.data["load_groups_to_show"]
|
||||
|
||||
|
||||
def update_activity_type(self, context):
|
||||
def update_activity_type(self: "BIMStructuralProperties", context: bpy.types.Context) -> None:
|
||||
LoadGroupDecorationData.is_loaded = False
|
||||
|
||||
|
||||
def get_applicable_structural_load_types(self, context):
|
||||
def get_applicable_structural_load_types(
|
||||
self: "BIMStructuralProperties", context: bpy.types.Context
|
||||
) -> list[tuple[str, str, str]]:
|
||||
if not StructuralLoadCasesData.is_loaded:
|
||||
StructuralLoadCasesData.load()
|
||||
return StructuralLoadCasesData.data["applicable_structural_load_types"]
|
||||
|
||||
|
||||
def updateApplicableStructuralLoadTypes(self, context):
|
||||
def updateApplicableStructuralLoadTypes(self: "BIMStructuralProperties", context: bpy.types.Context) -> None:
|
||||
StructuralLoadCasesData.data["applicable_structural_load_types"] = (
|
||||
StructuralLoadCasesData.applicable_structural_load_types()
|
||||
)
|
||||
|
||||
|
||||
def get_applicable_structural_loads(self, context):
|
||||
def get_applicable_structural_loads(
|
||||
self: "BIMStructuralProperties", context: bpy.types.Context
|
||||
) -> list[tuple[str, str, str]]:
|
||||
if not StructuralLoadCasesData.is_loaded:
|
||||
StructuralLoadCasesData.load()
|
||||
return StructuralLoadCasesData.data["applicable_structural_loads"]
|
||||
|
||||
|
||||
def get_structural_load_types(self, context):
|
||||
def get_structural_load_types(
|
||||
self: "BIMStructuralProperties", context: bpy.types.Context
|
||||
) -> list[tuple[str, str, str]]:
|
||||
if not StructuralLoadsData.is_loaded:
|
||||
StructuralLoadsData.load()
|
||||
return StructuralLoadsData.data["structural_load_types"]
|
||||
|
||||
|
||||
def get_boundary_condition_types(self, context):
|
||||
def get_boundary_condition_types(
|
||||
self: "BIMStructuralProperties", context: bpy.types.Context
|
||||
) -> list[tuple[str, str, str]]:
|
||||
if not BoundaryConditionsData.is_loaded:
|
||||
BoundaryConditionsData.load()
|
||||
return BoundaryConditionsData.data["boundary_condition_types"]
|
||||
|
||||
|
||||
def updateAxisAngle(self, context):
|
||||
def updateAxisAngle(self: "BIMObjectStructuralProperties", context: bpy.types.Context) -> None:
|
||||
if not self.axis_empty:
|
||||
return
|
||||
obj = context.active_object
|
||||
assert obj and isinstance(obj.data, bpy.types.Mesh)
|
||||
empty = self.axis_empty
|
||||
x_axis = obj.data.vertices[1].co - obj.data.vertices[0].co
|
||||
empty.location = obj.data.vertices[0].co
|
||||
@@ -92,10 +102,11 @@ def updateAxisAngle(self, context):
|
||||
empty.rotation_euler[0] = radians(self.axis_angle)
|
||||
|
||||
|
||||
def updateConnectionCS(self, context):
|
||||
def updateConnectionCS(self: "BIMObjectStructuralProperties", context: bpy.types.Context) -> None:
|
||||
if not self.ccs_empty:
|
||||
return
|
||||
obj = context.active_object
|
||||
assert obj and isinstance(obj.data, bpy.types.Mesh)
|
||||
empty = self.ccs_empty
|
||||
empty.location = obj.data.vertices[0].co
|
||||
empty.rotation_mode = "XYZ"
|
||||
@@ -108,24 +119,39 @@ class StructuralAnalysisModel(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
ifc_definition_id: int
|
||||
|
||||
|
||||
class StructuralActivity(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
applied_load_class: StringProperty(name="Applied Load Class")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
applied_load_class: str
|
||||
ifc_definition_id: int
|
||||
|
||||
|
||||
class StructuralLoad(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
number_of_inverse_references: IntProperty(name="Number of Inverse References")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
ifc_definition_id: int
|
||||
number_of_inverse_references: int
|
||||
|
||||
|
||||
class BoundaryCondition(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
ifc_definition_id: IntProperty(name="IFC Definition ID")
|
||||
number_of_inverse_references: IntProperty(name="Number of Inverse References")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
ifc_definition_id: int
|
||||
number_of_inverse_references: int
|
||||
|
||||
|
||||
class BIMStructuralProperties(PropertyGroup):
|
||||
structural_analysis_model_attributes: CollectionProperty(
|
||||
@@ -187,6 +213,45 @@ class BIMStructuralProperties(PropertyGroup):
|
||||
)
|
||||
load_group_to_show: EnumProperty(items=get_load_groups_to_show, name="Load Groups")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
structural_analysis_model_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
is_editing: bool
|
||||
structural_analysis_models: bpy.types.bpy_prop_collection_idprop[StructuralAnalysisModel]
|
||||
active_structural_analysis_model_index: int
|
||||
active_structural_analysis_model_id: int
|
||||
load_case_editing_type: str
|
||||
load_case_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
active_load_case_id: int
|
||||
load_group_editing_type: str
|
||||
active_load_group_id: int
|
||||
applicable_structural_load_types: str
|
||||
applicable_structural_loads: str
|
||||
load_group_activities: bpy.types.bpy_prop_collection_idprop[StructuralActivity]
|
||||
active_load_group_activity_index: int
|
||||
|
||||
structural_loads: bpy.types.bpy_prop_collection_idprop[StructuralLoad]
|
||||
active_structural_load_index: int
|
||||
active_structural_load_id: int
|
||||
is_editing_loads: bool
|
||||
structural_load_types: str
|
||||
structural_load_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
filtered_structural_loads: bool
|
||||
|
||||
boundary_conditions: bpy.types.bpy_prop_collection_idprop[BoundaryCondition]
|
||||
active_boundary_condition_index: int
|
||||
active_boundary_condition_id: int
|
||||
is_editing_boundary_conditions: bool
|
||||
boundary_condition_types: str
|
||||
boundary_condition_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
filtered_boundary_conditions: bool
|
||||
|
||||
show_loads: bool
|
||||
update_load_repr: bool
|
||||
enable_repr_auto_update: bool
|
||||
reference_frame: str
|
||||
activity_type: str
|
||||
load_group_to_show: str
|
||||
|
||||
|
||||
class BIMObjectStructuralProperties(PropertyGroup):
|
||||
boundary_condition_attributes: CollectionProperty(name="Boundary Condition Attributes", type=Attribute)
|
||||
@@ -203,3 +268,19 @@ class BIMObjectStructuralProperties(PropertyGroup):
|
||||
ccs_y_angle: FloatProperty(name="Connection CS Y Angle", update=updateConnectionCS)
|
||||
ccs_z_angle: FloatProperty(name="Connection CS Z Angle", update=updateConnectionCS)
|
||||
ccs_empty: PointerProperty(name="CCS Empty", type=bpy.types.Object)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
boundary_condition_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
|
||||
active_boundary_condition: int
|
||||
active_connects_structural_member: int
|
||||
relating_structural_member: Union[bpy.types.Object, None]
|
||||
is_editing_axis: bool
|
||||
axis_angle: float
|
||||
axis_empty: Union[bpy.types.Object, None]
|
||||
|
||||
# relating_structural_activity: Union[bpy.types.Object, None]
|
||||
is_editing_connection_cs: bool
|
||||
ccs_x_angle: float
|
||||
ccs_y_angle: float
|
||||
ccs_z_angle: float
|
||||
ccs_empty: Union[bpy.types.Object, None]
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.tool as tool
|
||||
import bonsai.bim.helper
|
||||
@@ -31,9 +32,25 @@ from bonsai.bim.module.structural.data import (
|
||||
StructuralConnectionData,
|
||||
BoundaryConditionsData,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Any, Union
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.structural.prop import (
|
||||
BIMStructuralProperties,
|
||||
BIMObjectStructuralProperties,
|
||||
BoundaryCondition,
|
||||
StructuralLoad,
|
||||
StructuralActivity,
|
||||
StructuralAnalysisModel,
|
||||
)
|
||||
|
||||
|
||||
def draw_boundary_condition_ui(layout, boundary_condition, connection_id, props):
|
||||
def draw_boundary_condition_ui(
|
||||
layout: bpy.types.UILayout,
|
||||
boundary_condition: dict[str, Any],
|
||||
connection_id: int,
|
||||
props: BIMObjectStructuralProperties,
|
||||
) -> None:
|
||||
row = layout.row(align=True)
|
||||
if not boundary_condition:
|
||||
row.label(text="No Boundary Condition Found", icon="CON_TRACKTO")
|
||||
@@ -59,11 +76,13 @@ def draw_boundary_condition_ui(layout, boundary_condition, connection_id, props)
|
||||
draw_boundary_condition_read_only_ui(layout, boundary_condition)
|
||||
|
||||
|
||||
def draw_boundary_condition_editable_ui(layout: bpy.types.UILayout, props: bpy.types.PropertyGroup) -> None:
|
||||
def draw_boundary_condition_editable_ui(
|
||||
layout: bpy.types.UILayout, props: Union[BIMStructuralProperties, BIMObjectStructuralProperties]
|
||||
) -> None:
|
||||
draw_attributes(props.boundary_condition_attributes, layout)
|
||||
|
||||
|
||||
def draw_boundary_condition_read_only_ui(layout, boundary_condition):
|
||||
def draw_boundary_condition_read_only_ui(layout: bpy.types.UILayout, boundary_condition: dict[str, Any]) -> None:
|
||||
for attribute in boundary_condition["attributes"]:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=attribute["name"])
|
||||
@@ -100,11 +119,15 @@ class BIM_PT_structural_boundary_conditions(Panel):
|
||||
if not StructuralBoundaryConditionsData.is_loaded:
|
||||
StructuralBoundaryConditionsData.load()
|
||||
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
self.props = tool.Structural.get_object_structural_props(obj)
|
||||
|
||||
draw_boundary_condition_ui(
|
||||
self.layout,
|
||||
StructuralBoundaryConditionsData.data["boundary_condition"],
|
||||
StructuralBoundaryConditionsData.data["connection_id"],
|
||||
context.active_object.BIMStructuralProperties,
|
||||
self.props,
|
||||
)
|
||||
|
||||
|
||||
@@ -135,7 +158,9 @@ class BIM_PT_connected_structural_members(Panel):
|
||||
if not ConnectedStructuralMembersData.is_loaded:
|
||||
ConnectedStructuralMembersData.load()
|
||||
|
||||
self.props = context.active_object.BIMStructuralProperties
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
self.props = tool.Structural.get_object_structural_props(obj)
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "relating_structural_member", text="", icon="CON_TRACKTO")
|
||||
@@ -188,7 +213,9 @@ class BIM_PT_structural_member(Panel):
|
||||
if not StructuralMemberData.is_loaded:
|
||||
StructuralMemberData.load()
|
||||
|
||||
self.props = context.active_object.BIMStructuralProperties
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
self.props = tool.Structural.get_object_structural_props(obj)
|
||||
|
||||
if StructuralMemberData.data["active_object_class"] == "IfcStructuralCurveMember":
|
||||
if self.props.is_editing_axis:
|
||||
@@ -231,7 +258,9 @@ class BIM_PT_structural_connection(Panel):
|
||||
if not StructuralConnectionData.is_loaded:
|
||||
StructuralConnectionData.load()
|
||||
|
||||
self.props = context.active_object.BIMStructuralProperties
|
||||
obj = context.active_object
|
||||
assert obj
|
||||
self.props = tool.Structural.get_object_structural_props(obj)
|
||||
|
||||
if StructuralConnectionData.data["active_object_class"] == "IfcStructuralCurveConnection":
|
||||
if self.props.is_editing_axis:
|
||||
@@ -281,7 +310,7 @@ class BIM_PT_structural_analysis_models(Panel):
|
||||
if not StructuralAnalysisModelsData.is_loaded:
|
||||
StructuralAnalysisModelsData.load()
|
||||
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props = tool.Structural.get_structural_props()
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(
|
||||
@@ -309,7 +338,16 @@ class BIM_PT_structural_analysis_models(Panel):
|
||||
|
||||
|
||||
class BIM_UL_structural_analysis_models(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context: bpy.types.Context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMStructuralProperties,
|
||||
item: StructuralAnalysisModel,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.name)
|
||||
@@ -324,10 +362,10 @@ class BIM_UL_structural_analysis_models(UIList):
|
||||
op = row.operator("bim.assign_structural_analysis_model", text="", icon="KEYFRAME", emboss=False)
|
||||
op.structural_analysis_model = item.ifc_definition_id
|
||||
|
||||
if context.scene.BIMStructuralProperties.active_structural_analysis_model_id == item.ifc_definition_id:
|
||||
if data.active_structural_analysis_model_id == item.ifc_definition_id:
|
||||
row.operator("bim.edit_structural_analysis_model", text="", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_structural_analysis_model", text="", icon="CANCEL")
|
||||
elif context.scene.BIMStructuralProperties.active_structural_analysis_model_id:
|
||||
elif data.active_structural_analysis_model_id:
|
||||
op = row.operator("bim.remove_structural_analysis_model", text="", icon="X")
|
||||
op.structural_analysis_model = item.ifc_definition_id
|
||||
else:
|
||||
@@ -354,7 +392,7 @@ class BIM_PT_structural_load_cases(Panel):
|
||||
if not StructuralLoadCasesData.is_loaded:
|
||||
StructuralLoadCasesData.load()
|
||||
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props = tool.Structural.get_structural_props()
|
||||
|
||||
row = self.layout.row()
|
||||
row.operator("bim.add_structural_load_case", icon="ADD")
|
||||
@@ -425,7 +463,16 @@ class BIM_PT_structural_load_cases(Panel):
|
||||
|
||||
|
||||
class BIM_UL_structural_activities(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMStructuralProperties,
|
||||
item: StructuralActivity,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.name)
|
||||
@@ -446,8 +493,7 @@ class BIM_PT_show_structural_activities(Panel):
|
||||
return file and hasattr(file, "schema") and file.schema != "IFC2X3"
|
||||
|
||||
def draw(self, context):
|
||||
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props = tool.Structural.get_structural_props()
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.operator(
|
||||
@@ -480,7 +526,7 @@ class BIM_PT_structural_loads(Panel):
|
||||
if not StructuralLoadsData.is_loaded:
|
||||
StructuralLoadsData.load()
|
||||
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props = tool.Structural.get_structural_props()
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=f"{StructuralLoadsData.data['total_loads']} Structural Loads Found", icon="ANIM_DATA")
|
||||
@@ -513,16 +559,25 @@ class BIM_PT_structural_loads(Panel):
|
||||
|
||||
|
||||
class BIM_UL_structural_loads(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMStructuralProperties,
|
||||
item: StructuralLoad,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=f"{item.name} ({item.number_of_inverse_references})")
|
||||
row.label(text=StructuralLoadsData.data["load_classes"][item.ifc_definition_id])
|
||||
|
||||
if context.scene.BIMStructuralProperties.active_structural_load_id == item.ifc_definition_id:
|
||||
if data.active_structural_load_id == item.ifc_definition_id:
|
||||
row.operator("bim.edit_structural_load", text="", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_structural_load", text="", icon="CANCEL")
|
||||
elif context.scene.BIMStructuralProperties.active_structural_load_id:
|
||||
elif data.active_structural_load_id:
|
||||
op = row.operator("bim.remove_structural_load", text="", icon="X")
|
||||
op.structural_load = item.ifc_definition_id
|
||||
else:
|
||||
@@ -549,7 +604,7 @@ class BIM_PT_boundary_conditions(Panel):
|
||||
if not BoundaryConditionsData.is_loaded:
|
||||
BoundaryConditionsData.load()
|
||||
|
||||
self.props = context.scene.BIMStructuralProperties
|
||||
self.props = tool.Structural.get_structural_props()
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(
|
||||
@@ -587,16 +642,25 @@ class BIM_PT_boundary_conditions(Panel):
|
||||
|
||||
|
||||
class BIM_UL_boundary_conditions(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
def draw_item(
|
||||
self,
|
||||
context,
|
||||
layout: bpy.types.UILayout,
|
||||
data: BIMStructuralProperties,
|
||||
item: BoundaryCondition,
|
||||
icon,
|
||||
active_data,
|
||||
active_propname,
|
||||
):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=f"{item.name} ({item.number_of_inverse_references})")
|
||||
row.label(text=BoundaryConditionsData.data["condition_classes"][item.ifc_definition_id])
|
||||
|
||||
if context.scene.BIMStructuralProperties.active_boundary_condition_id == item.ifc_definition_id:
|
||||
if data.active_boundary_condition_id == item.ifc_definition_id:
|
||||
row.operator("bim.edit_boundary_condition", text="", icon="CHECKMARK")
|
||||
row.operator("bim.disable_editing_boundary_condition", text="", icon="CANCEL")
|
||||
elif context.scene.BIMStructuralProperties.active_boundary_condition_id:
|
||||
elif data.active_boundary_condition_id:
|
||||
op = row.operator("bim.remove_boundary_condition", text="", icon="X")
|
||||
op.boundary_condition = item.ifc_definition_id
|
||||
else:
|
||||
|
||||
@@ -54,7 +54,7 @@ class StructuralToolUI:
|
||||
@classmethod
|
||||
def draw(cls, context, layout):
|
||||
cls.layout = layout
|
||||
# cls.props = context.scene.BIMStructuralProperties
|
||||
cls.props = tool.Structural.get_structural_props()
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
if not tool.Ifc.get():
|
||||
@@ -99,12 +99,12 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
|
||||
return operator.description or ""
|
||||
|
||||
def _execute(self, context):
|
||||
# self.props = context.scene.BIMStructuralProperties
|
||||
# self.props = tool.Structural.get_structural_props()
|
||||
getattr(self, f"hotkey_{self.hotkey}")()
|
||||
|
||||
def invoke(self, context, event):
|
||||
# https://blender.stackexchange.com/questions/276035/how-do-i-make-operators-remember-their-property-values-when-called-from-a-hotkey
|
||||
# self.props = context.scene.BIMStructuralProperties
|
||||
# self.props = tool.Structural.get_structural_props()
|
||||
return self.execute(context)
|
||||
|
||||
def draw(self, context):
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import bonsai.core.tool
|
||||
import bonsai.bim.schema
|
||||
@@ -24,12 +25,19 @@ import ifcopenshell
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.element
|
||||
from mathutils import Vector
|
||||
from typing import Optional, Union, Literal
|
||||
from typing import Optional, Union, Literal, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.qto.prop import BIMQtoProperties
|
||||
|
||||
QuantityTypes = Literal["Q_LENGTH", "Q_AREA", "Q_VOLUME"]
|
||||
|
||||
|
||||
class Qto(bonsai.core.tool.Qto):
|
||||
@classmethod
|
||||
def get_qto_props(cls) -> BIMQtoProperties:
|
||||
return bpy.context.scene.BIMQtoProperties
|
||||
|
||||
@classmethod
|
||||
def get_radius_of_selected_vertices(cls, obj: bpy.types.Object) -> float:
|
||||
selected_verts = [v.co for v in obj.data.vertices if v.select]
|
||||
@@ -41,7 +49,8 @@ class Qto(bonsai.core.tool.Qto):
|
||||
|
||||
@classmethod
|
||||
def set_qto_result(cls, result: float) -> None:
|
||||
bpy.context.scene.BIMQtoProperties.qto_result = str(round(result, 3))
|
||||
props = cls.get_qto_props()
|
||||
props.qto_result = str(round(result, 3))
|
||||
|
||||
@classmethod
|
||||
def get_rounded_value(cls, new_quantity: float) -> float:
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import annotations
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.representation
|
||||
@@ -23,30 +24,46 @@ import json
|
||||
import bonsai.bim.helper
|
||||
import bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
from typing import Union, Any
|
||||
from typing import Union, Any, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from bonsai.bim.module.structural.prop import BIMStructuralProperties, BIMObjectStructuralProperties
|
||||
|
||||
|
||||
class Structural(bonsai.core.tool.Structural):
|
||||
@classmethod
|
||||
def get_structural_props(cls) -> BIMStructuralProperties:
|
||||
return bpy.context.scene.BIMStructuralProperties
|
||||
|
||||
@classmethod
|
||||
def get_object_structural_props(cls, obj: bpy.types.Object) -> BIMObjectStructuralProperties:
|
||||
return obj.BIMStructuralProperties
|
||||
|
||||
@classmethod
|
||||
def disable_editing_structural_analysis_model(cls) -> None:
|
||||
bpy.context.scene.BIMStructuralProperties.active_structural_analysis_model_id = 0
|
||||
props = cls.get_structural_props()
|
||||
props.active_structural_analysis_model_id = 0
|
||||
|
||||
@classmethod
|
||||
def disable_structural_analysis_model_editing_ui(cls) -> None:
|
||||
bpy.context.scene.BIMStructuralProperties.is_editing = False
|
||||
props = cls.get_structural_props()
|
||||
props.is_editing = False
|
||||
|
||||
@classmethod
|
||||
def enable_editing_structural_analysis_model(cls, model: Union[int, None]) -> None:
|
||||
if model:
|
||||
bpy.context.scene.BIMStructuralProperties.active_structural_analysis_model_id = model
|
||||
props = cls.get_structural_props()
|
||||
props.active_structural_analysis_model_id = model
|
||||
|
||||
@classmethod
|
||||
def enable_structural_analysis_model_editing_ui(cls) -> None:
|
||||
bpy.context.scene.BIMStructuralProperties.is_editing = True
|
||||
props = cls.get_structural_props()
|
||||
props.is_editing = True
|
||||
|
||||
@classmethod
|
||||
def enabled_structural_analysis_model_editing_ui(cls) -> bool:
|
||||
return bpy.context.scene.BIMStructuralProperties.is_editing
|
||||
props = cls.get_structural_props()
|
||||
return props.is_editing
|
||||
|
||||
@classmethod
|
||||
def ensure_representation_contexts(cls) -> None:
|
||||
@@ -71,7 +88,7 @@ class Structural(bonsai.core.tool.Structural):
|
||||
|
||||
@classmethod
|
||||
def get_active_structural_analysis_model(cls) -> ifcopenshell.entity_instance:
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = cls.get_structural_props()
|
||||
model = tool.Ifc.get().by_id(props.active_structural_analysis_model_id)
|
||||
return model
|
||||
|
||||
@@ -120,13 +137,13 @@ class Structural(bonsai.core.tool.Structural):
|
||||
|
||||
@classmethod
|
||||
def get_structural_analysis_model_attributes(cls) -> dict[str, Any]:
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = cls.get_structural_props()
|
||||
attributes = bonsai.bim.helper.export_attributes(props.structural_analysis_model_attributes)
|
||||
return attributes
|
||||
|
||||
@classmethod
|
||||
def load_structural_analysis_model_attributes(cls, data: dict[str, Any]) -> None:
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = cls.get_structural_props()
|
||||
props.structural_analysis_model_attributes.clear()
|
||||
schema = tool.Ifc.schema()
|
||||
for attribute in schema.declaration_by_name("IfcStructuralAnalysisModel").all_attributes():
|
||||
@@ -149,7 +166,7 @@ class Structural(bonsai.core.tool.Structural):
|
||||
@classmethod
|
||||
def load_structural_analysis_models(cls) -> None:
|
||||
models = tool.Structural.get_ifc_structural_analysis_models()
|
||||
props = bpy.context.scene.BIMStructuralProperties
|
||||
props = cls.get_structural_props()
|
||||
props.structural_analysis_models.clear()
|
||||
for ifc_definition_id, model in models.items():
|
||||
new = props.structural_analysis_models.add()
|
||||
|
||||
@@ -42,7 +42,8 @@ class TestGetRadiusOfSelectedVertices(test.bim.bootstrap.NewFile):
|
||||
class TestSetQtoResult(test.bim.bootstrap.NewFile):
|
||||
def test_run(self):
|
||||
subject.set_qto_result(123.4567)
|
||||
assert bpy.context.scene.BIMQtoProperties.qto_result == "123.457"
|
||||
props = tool.Qto.get_qto_props()
|
||||
assert props.qto_result == "123.457"
|
||||
|
||||
|
||||
class TestGetRoundedValue(test.bim.bootstrap.NewFile):
|
||||
|
||||
Reference in New Issue
Block a user