mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-25 09:32:37 +00:00
Minor fix.
This commit is contained in:
@@ -155,7 +155,7 @@ class IfcExporter:
|
|||||||
float(props.blender_x_axis_ordinate),
|
float(props.blender_x_axis_ordinate),
|
||||||
)
|
)
|
||||||
if not np.allclose(ifc_matrix, blender_matrix, atol=0.0001):
|
if not np.allclose(ifc_matrix, blender_matrix, atol=0.0001):
|
||||||
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj)
|
blenderbim.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
|
||||||
return element
|
return element
|
||||||
|
|
||||||
def sync_grid_axis_object_placement(self, obj, element):
|
def sync_grid_axis_object_placement(self, obj, element):
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class EditObjectPlacement(bpy.types.Operator, Operator):
|
|||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
objs = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects
|
objs = [bpy.data.objects.get(self.obj)] if self.obj else context.selected_objects
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
core.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj)
|
core.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
|
||||||
|
|
||||||
|
|
||||||
class AddRepresentation(bpy.types.Operator, Operator):
|
class AddRepresentation(bpy.types.Operator, Operator):
|
||||||
@@ -153,7 +153,7 @@ class UpdateRepresentation(bpy.types.Operator):
|
|||||||
ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"axis_curve": obj, "grid_axis": product})
|
ifcopenshell.api.run("grid.create_axis_curve", self.file, **{"axis_curve": obj, "grid_axis": product})
|
||||||
return
|
return
|
||||||
|
|
||||||
core.edit_object_placement(tool.Ifc, tool.Surveyor, obj=obj)
|
core.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj)
|
||||||
|
|
||||||
old_representation = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
|
old_representation = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
|
||||||
context_of_items = old_representation.ContextOfItems
|
context_of_items = old_representation.ContextOfItems
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import blenderbim.tool as tool
|
|||||||
|
|
||||||
def refresh():
|
def refresh():
|
||||||
AuthoringData.is_loaded = False
|
AuthoringData.is_loaded = False
|
||||||
WorkspaceData.is_loaded = False
|
|
||||||
|
|
||||||
|
|
||||||
class AuthoringData:
|
class AuthoringData:
|
||||||
@@ -31,21 +30,23 @@ class AuthoringData:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls):
|
def load(cls):
|
||||||
|
cls.is_loaded = True
|
||||||
cls.data = {
|
cls.data = {
|
||||||
"ifc_classes": cls.ifc_classes(),
|
"ifc_classes": cls.ifc_classes(),
|
||||||
"relating_types": cls.relating_types(),
|
"relating_types": cls.relating_types(),
|
||||||
}
|
}
|
||||||
cls.is_loaded = True
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def ifc_classes(cls):
|
def ifc_classes(cls):
|
||||||
results = []
|
results = []
|
||||||
classes = set([e.is_a() for e in tool.Ifc.get().by_type("IfcElementType")])
|
classes = {e.is_a() for e in tool.Ifc.get().by_type("IfcElementType")}
|
||||||
results.extend([(c, c, "") for c in sorted(classes)])
|
results.extend([(c, c, "") for c in sorted(classes)])
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def relating_types(cls):
|
def relating_types(cls):
|
||||||
|
if not cls.ifc_classes():
|
||||||
|
return []
|
||||||
results = []
|
results = []
|
||||||
ifc_class = bpy.context.scene.BIMModelProperties.ifc_class
|
ifc_class = bpy.context.scene.BIMModelProperties.ifc_class
|
||||||
if ifc_class:
|
if ifc_class:
|
||||||
@@ -53,7 +54,3 @@ class AuthoringData:
|
|||||||
results.extend(sorted(elements, key=lambda s: s[1]))
|
results.extend(sorted(elements, key=lambda s: s[1]))
|
||||||
return results
|
return results
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceData(AuthoringData):
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import bpy
|
|||||||
import blenderbim.bim.module.type.prop as type_prop
|
import blenderbim.bim.module.type.prop as type_prop
|
||||||
from bpy.types import WorkSpaceTool
|
from bpy.types import WorkSpaceTool
|
||||||
from blenderbim.bim.ifc import IfcStore
|
from blenderbim.bim.ifc import IfcStore
|
||||||
from blenderbim.bim.module.model.data import WorkspaceData
|
from blenderbim.bim.module.model.data import AuthoringData
|
||||||
|
|
||||||
|
|
||||||
class BimTool(WorkSpaceTool):
|
class BimTool(WorkSpaceTool):
|
||||||
@@ -52,19 +52,19 @@ class BimTool(WorkSpaceTool):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def draw_settings(context, layout, tool):
|
def draw_settings(context, layout, tool):
|
||||||
if not WorkspaceData.is_loaded:
|
if not AuthoringData.is_loaded:
|
||||||
WorkspaceData.load()
|
AuthoringData.load()
|
||||||
|
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
if not IfcStore.get_file():
|
if not IfcStore.get_file():
|
||||||
row.label(text="No IFC Project", icon="ERROR")
|
row.label(text="No IFC Project", icon="ERROR")
|
||||||
return
|
return
|
||||||
props = context.scene.BIMModelProperties
|
props = context.scene.BIMModelProperties
|
||||||
if WorkspaceData.data["ifc_classes"]:
|
if AuthoringData.data["ifc_classes"]:
|
||||||
row.prop(props, "ifc_class", text="")
|
row.prop(props, "ifc_class", text="")
|
||||||
else:
|
else:
|
||||||
row.label(text="No IFC Class")
|
row.label(text="No IFC Class")
|
||||||
if WorkspaceData.data["relating_types"]:
|
if AuthoringData.data["relating_types"]:
|
||||||
row.prop(props, "relating_type", text="")
|
row.prop(props, "relating_type", text="")
|
||||||
else:
|
else:
|
||||||
row.label(text="No Relating Type")
|
row.label(text="No Relating Type")
|
||||||
@@ -75,7 +75,7 @@ class BimTool(WorkSpaceTool):
|
|||||||
row.label(text="", icon="EVENT_SHIFT")
|
row.label(text="", icon="EVENT_SHIFT")
|
||||||
row.label(text="Add Type Instance", icon="EVENT_A")
|
row.label(text="Add Type Instance", icon="EVENT_A")
|
||||||
|
|
||||||
if not ifc_classes_is_empty:
|
if AuthoringData.data["ifc_classes"]:
|
||||||
if props.ifc_class == "IfcWallType":
|
if props.ifc_class == "IfcWallType":
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.label(text="Join")
|
row.label(text="Join")
|
||||||
@@ -147,9 +147,9 @@ class Hotkey(bpy.types.Operator):
|
|||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
self.props = context.scene.BIMModelProperties
|
self.props = context.scene.BIMModelProperties
|
||||||
self.ifc_classes_is_empty = True
|
self.has_ifc_class = True
|
||||||
try:
|
try:
|
||||||
self.ifc_classes_is_empty = bool(self.props.ifc_class)
|
self.has_ifc_class = bool(self.props.ifc_class)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
getattr(self, f"hotkey_{self.hotkey}")()
|
getattr(self, f"hotkey_{self.hotkey}")()
|
||||||
@@ -159,13 +159,13 @@ class Hotkey(bpy.types.Operator):
|
|||||||
bpy.ops.bim.add_type_instance()
|
bpy.ops.bim.add_type_instance()
|
||||||
|
|
||||||
def hotkey_S_C(self):
|
def hotkey_S_C(self):
|
||||||
if not self.ifc_classes_is_empty and self.props.ifc_class == "IfcWallType":
|
if self.has_ifc_class and self.props.ifc_class == "IfcWallType":
|
||||||
bpy.ops.bim.align_wall(align_type="CENTERLINE")
|
bpy.ops.bim.align_wall(align_type="CENTERLINE")
|
||||||
else:
|
else:
|
||||||
bpy.ops.bim.align_product(align_type="CENTERLINE")
|
bpy.ops.bim.align_product(align_type="CENTERLINE")
|
||||||
|
|
||||||
def hotkey_S_E(self):
|
def hotkey_S_E(self):
|
||||||
if self.ifc_classes_is_empty:
|
if not self.has_ifc_class:
|
||||||
return
|
return
|
||||||
if self.props.ifc_class == "IfcWallType":
|
if self.props.ifc_class == "IfcWallType":
|
||||||
bpy.ops.bim.join_wall(join_type="T")
|
bpy.ops.bim.join_wall(join_type="T")
|
||||||
@@ -173,13 +173,13 @@ class Hotkey(bpy.types.Operator):
|
|||||||
bpy.ops.bim.extend_profile()
|
bpy.ops.bim.extend_profile()
|
||||||
|
|
||||||
def hotkey_S_V(self):
|
def hotkey_S_V(self):
|
||||||
if not self.ifc_classes_is_empty and self.props.ifc_class == "IfcWallType":
|
if self.has_ifc_class and self.props.ifc_class == "IfcWallType":
|
||||||
bpy.ops.bim.align_wall(align_type="INTERIOR")
|
bpy.ops.bim.align_wall(align_type="INTERIOR")
|
||||||
else:
|
else:
|
||||||
bpy.ops.bim.align_product(align_type="POSITIVE")
|
bpy.ops.bim.align_product(align_type="POSITIVE")
|
||||||
|
|
||||||
def hotkey_S_X(self):
|
def hotkey_S_X(self):
|
||||||
if not self.ifc_classes_is_empty and self.props.ifc_class == "IfcWallType":
|
if self.has_ifc_class and self.props.ifc_class == "IfcWallType":
|
||||||
if bpy.ops.bim.align_wall.poll():
|
if bpy.ops.bim.align_wall.poll():
|
||||||
bpy.ops.bim.align_wall(align_type="EXTERIOR")
|
bpy.ops.bim.align_wall(align_type="EXTERIOR")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -19,9 +19,10 @@
|
|||||||
import blenderbim.core.style
|
import blenderbim.core.style
|
||||||
|
|
||||||
|
|
||||||
def edit_object_placement(ifc, surveyor, obj=None):
|
def edit_object_placement(ifc, geometry, surveyor, obj=None):
|
||||||
element = ifc.get_entity(obj)
|
element = ifc.get_entity(obj)
|
||||||
if element:
|
if element:
|
||||||
|
geometry.clear_scale(obj)
|
||||||
ifc.run("geometry.edit_object_placement", product=element, matrix=surveyor.get_absolute_matrix(obj))
|
ifc.run("geometry.edit_object_placement", product=element, matrix=surveyor.get_absolute_matrix(obj))
|
||||||
|
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ def add_representation(
|
|||||||
if not element:
|
if not element:
|
||||||
return
|
return
|
||||||
|
|
||||||
edit_object_placement(ifc, surveyor, obj=obj)
|
edit_object_placement(ifc, geometry, surveyor, obj=obj)
|
||||||
data = geometry.get_object_data(obj)
|
data = geometry.get_object_data(obj)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class Context:
|
|||||||
class Geometry:
|
class Geometry:
|
||||||
def change_object_data(cls, obj, data, is_global=False): pass
|
def change_object_data(cls, obj, data, is_global=False): pass
|
||||||
def clear_modifiers(cls, obj): pass
|
def clear_modifiers(cls, obj): pass
|
||||||
|
def clear_scale(cls, obj): pass
|
||||||
def create_dynamic_voids(cls, obj): pass
|
def create_dynamic_voids(cls, obj): pass
|
||||||
def delete_data(cls, data): pass
|
def delete_data(cls, data): pass
|
||||||
def does_object_have_mesh_with_faces(cls, obj): pass
|
def does_object_have_mesh_with_faces(cls, obj): pass
|
||||||
|
|||||||
@@ -39,6 +39,17 @@ class Geometry(blenderbim.core.tool.Geometry):
|
|||||||
for modifier in obj.modifiers:
|
for modifier in obj.modifiers:
|
||||||
obj.modifiers.remove(modifier)
|
obj.modifiers.remove(modifier)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def clear_scale(cls, obj):
|
||||||
|
if obj.scale != Vector((1.0, 1.0, 1.0)):
|
||||||
|
if obj.data.users == 1:
|
||||||
|
context_override = {}
|
||||||
|
context_override["object"] = context_override["active_object"] = obj
|
||||||
|
context_override["selected_objects"] = context_override["selected_editable_objects"] = [obj]
|
||||||
|
bpy.ops.object.transform_apply(context_override, location=False, rotation=False, scale=True)
|
||||||
|
else:
|
||||||
|
obj.scale = Vector((1.0, 1.0, 1.0))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_dynamic_voids(cls, obj):
|
def create_dynamic_voids(cls, obj):
|
||||||
element = tool.Ifc.get_entity(obj)
|
element = tool.Ifc.get_entity(obj)
|
||||||
|
|||||||
@@ -22,19 +22,20 @@ from test.core.bootstrap import ifc, surveyor, geometry, style
|
|||||||
|
|
||||||
|
|
||||||
class TestEditObjectPlacement:
|
class TestEditObjectPlacement:
|
||||||
def predict(self, ifc, surveyor):
|
def predict(self, ifc, geometry, surveyor):
|
||||||
ifc.get_entity("obj").should_be_called().will_return("element")
|
ifc.get_entity("obj").should_be_called().will_return("element")
|
||||||
|
geometry.clear_scale("obj").should_be_called()
|
||||||
surveyor.get_absolute_matrix("obj").should_be_called().will_return("matrix")
|
surveyor.get_absolute_matrix("obj").should_be_called().will_return("matrix")
|
||||||
ifc.run("geometry.edit_object_placement", product="element", matrix="matrix").should_be_called()
|
ifc.run("geometry.edit_object_placement", product="element", matrix="matrix").should_be_called()
|
||||||
|
|
||||||
def test_run(self, ifc, surveyor):
|
def test_run(self, ifc, geometry, surveyor):
|
||||||
self.predict(ifc, surveyor)
|
self.predict(ifc, geometry, surveyor)
|
||||||
subject.edit_object_placement(ifc, surveyor, obj="obj")
|
subject.edit_object_placement(ifc, geometry, surveyor, obj="obj")
|
||||||
|
|
||||||
|
|
||||||
class TestAddRepresentation:
|
class TestAddRepresentation:
|
||||||
def test_run(self, ifc, geometry, style, surveyor):
|
def test_run(self, ifc, geometry, style, surveyor):
|
||||||
TestEditObjectPlacement.predict(self, ifc, surveyor)
|
TestEditObjectPlacement.predict(self, ifc, geometry, surveyor)
|
||||||
|
|
||||||
# Add representation
|
# Add representation
|
||||||
geometry.get_object_data("obj").should_be_called().will_return("data")
|
geometry.get_object_data("obj").should_be_called().will_return("data")
|
||||||
@@ -96,7 +97,7 @@ class TestAddRepresentation:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_not_handling_styles_if_representation_has_no_faces(self, ifc, geometry, style, surveyor):
|
def test_not_handling_styles_if_representation_has_no_faces(self, ifc, geometry, style, surveyor):
|
||||||
TestEditObjectPlacement.predict(self, ifc, surveyor)
|
TestEditObjectPlacement.predict(self, ifc, geometry, surveyor)
|
||||||
|
|
||||||
# Add representation
|
# Add representation
|
||||||
geometry.get_object_data("obj").should_be_called().will_return("data")
|
geometry.get_object_data("obj").should_be_called().will_return("data")
|
||||||
@@ -145,7 +146,7 @@ class TestAddRepresentation:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_only_updating_the_placement_if_there_is_no_object_data(self, ifc, geometry, style, surveyor):
|
def test_only_updating_the_placement_if_there_is_no_object_data(self, ifc, geometry, style, surveyor):
|
||||||
TestEditObjectPlacement.predict(self, ifc, surveyor)
|
TestEditObjectPlacement.predict(self, ifc, geometry, surveyor)
|
||||||
|
|
||||||
# Add representation
|
# Add representation
|
||||||
geometry.get_object_data("obj").should_be_called().will_return(None)
|
geometry.get_object_data("obj").should_be_called().will_return(None)
|
||||||
|
|||||||
@@ -61,6 +61,14 @@ class TestClearModifiers(NewFile):
|
|||||||
assert len(obj.modifiers) == 0
|
assert len(obj.modifiers) == 0
|
||||||
|
|
||||||
|
|
||||||
|
class TestClearScale(NewFile):
|
||||||
|
def test_run(self):
|
||||||
|
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
|
||||||
|
obj.scale[0] = 2
|
||||||
|
subject.clear_scale(obj)
|
||||||
|
assert list(obj.scale) == [1, 1, 1]
|
||||||
|
|
||||||
|
|
||||||
class TestCreateDynamicVoids(NewFile):
|
class TestCreateDynamicVoids(NewFile):
|
||||||
def test_run(self):
|
def test_run(self):
|
||||||
ifc = ifcopenshell.file()
|
ifc = ifcopenshell.file()
|
||||||
|
|||||||
@@ -66,15 +66,6 @@ class Usecase:
|
|||||||
return any([abs((tM @ v.co).z) > threshold for v in face.verts])
|
return any([abs((tM @ v.co).z) > threshold for v in face.verts])
|
||||||
|
|
||||||
def evaluate_geometry(self):
|
def evaluate_geometry(self):
|
||||||
if self.settings["blender_object"].scale != Vector((1., 1., 1.)):
|
|
||||||
if self.settings["blender_object"].data.users == 1:
|
|
||||||
context_override = {}
|
|
||||||
context_override["object"] = context_override["active_object"] = self.settings["blender_object"]
|
|
||||||
context_override["selected_objects"] = context_override["selected_editable_objects"] = [self.settings["blender_object"]]
|
|
||||||
bpy.ops.object.transform_apply(context_override, location=False, rotation=False, scale=True)
|
|
||||||
else:
|
|
||||||
self.settings["blender_object"].scale = Vector((1., 1., 1.))
|
|
||||||
|
|
||||||
for modifier in self.settings["blender_object"].modifiers:
|
for modifier in self.settings["blender_object"].modifiers:
|
||||||
if modifier.type == "BOOLEAN":
|
if modifier.type == "BOOLEAN":
|
||||||
modifier.show_viewport = False
|
modifier.show_viewport = False
|
||||||
|
|||||||
Reference in New Issue
Block a user